diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..c48a05d9 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,13 @@ +{ + "permissions": { + "allow": [ + "Bash(env)", + "Bash(curl:*)", + "Bash(git remote remove:*)", + "Bash(git remote set-url:*)", + "Bash(git add:*)" + ], + "deny": [], + "ask": [] + } +} \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..ea312ea6 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,147 @@ +# CLAUDE.md + +This file provides guidance to Claude Code when working with this Vulkan-based 3D engine codebase. + +## Project Overview + +A modern Vulkan-based 3D engine built on Sascha Willems' Vulkan examples framework, featuring procedural shape generation, scene management, and ImGui integration. The engine uses dynamic rendering (VK_KHR_dynamic_rendering) and C++20 standards. + +## Build System + +### Quick Build +```bash +# From project root (inihb/) +mkdir build && cd build +cmake .. && cmake --build . --config Release +``` + +### Platform-Specific +- **Windows**: `cmake .. -G "Visual Studio 16 2019" -A x64` +- **Linux**: `cmake .. && make -j$(nproc)` +- **Output**: `build/bin/Release/ProceduralEngine3D.exe` + +### Dependencies +- Vulkan SDK (required) +- C++20 compatible compiler +- CMake 3.10.0+ + +## Architecture + +### Core Systems +- **Application** (`src/core/Application.cpp`): Main Vulkan application class inheriting from VulkanExampleBase +- **Base Framework** (`base/`): Sascha Willems' Vulkan infrastructure +- **Scene Management** (`src/scene/`): Object and shape management +- **UI System** (`src/ui/`): ImGui-based interface +- **Camera System** (`base/camera.hpp`): Orbit camera with focus functionality + +### Vulkan Features +- Dynamic rendering (no render passes/framebuffers) +- Modern Vulkan 1.3+ practices +- Multi-platform window system integration +- Validation layer support + +## Key Files + +### Core Components +- `src/core/Application.cpp` - Main application class with Vulkan setup +- `base/camera.hpp` - Camera system with orbit mode and F key focus +- `src/scene/SceneManager.cpp` - Scene graph and object management +- `src/ui/UIManager.cpp` - ImGui integration and panels + +### Vulkan Infrastructure (Sascha Willems Base) +- `base/VulkanExampleBase.h` - Main Vulkan framework +- `base/VulkanDevice.hpp` - Vulkan device abstraction +- `base/VulkanSwapChain.hpp` - Swapchain management +- `base/VulkanBuffer.hpp` - Buffer utilities + +### Build Configuration +- `CMakeLists.txt` - Main build configuration +- `BUILD.md` - Detailed build instructions + +## Camera System + +### F Key Focus Feature +The camera system supports focusing on selected objects: +- Press **F** to focus camera on selected object +- Automatically calculates optimal viewing distance +- Switches to orbit mode around focused object +- Mouse rotation orbits around the focused object center + +### Implementation Details +- `camera.focusOnObject()` - Sets orbit center and optimal distance +- `camera.updateOrbitPosition()` - Handles spherical coordinate positioning +- Hybrid system: standard Sascha camera + orbit mode using `glm::lookAt()` + +## Development Guidelines + +### Testing Changes +1. Build with `cmake --build . --config Release` +2. Run from `build/bin/Release/` +3. Use **F** key to test camera focus functionality +4. Check console output for debug information + +### Vulkan Debugging +- Enable validation layers with `-v` command line flag +- Use `--listgpus` to see available Vulkan devices +- Check `VK_LAYER_KHRONOS_validation` environment variable + +### Adding Features +- Follow Sascha Willems patterns for Vulkan code +- Use dynamic rendering (no render passes) +- Implement proper buffer management and synchronization +- Add ImGui panels for new features + +## Common Tasks + +### Build and Run +```bash +cd build +cmake --build . --config Release +bin/Release/ProceduralEngine3D.exe +``` + +### Shader Compilation +Shaders are in GLSL and compiled to SPIR-V: +- Location: `shaders/glsl/` +- Compiled automatically during build +- Use `glslc` or `glslangValidator` for manual compilation + +### Clean Build +```bash +rm -rf build && mkdir build && cd build +cmake .. && cmake --build . --config Release +``` + +### Camera Controls +- **Mouse**: Look around (standard mode) or orbit (after F key focus) +- **WASD**: Move camera +- **F**: Focus on selected object +- **Mouse Wheel**: Zoom (in orbit mode changes distance) + +## Command Line Options + +Available options (use `--help` for full list): +- `-v, --validation`: Enable validation layers +- `-w, --width`: Set window width +- `-h, --height`: Set window height +- `-f, --fullscreen`: Start in fullscreen +- `-g, --gpu`: Select GPU device +- `--listgpus`: List available Vulkan devices + +## Technical Notes + +### Modern Vulkan Usage +- Uses `VK_KHR_dynamic_rendering` extension +- No traditional render passes or framebuffers +- Leverages Vulkan 1.3+ features where available +- Proper synchronization with timeline semaphores + +### Memory Management +- Buffer utilities handle staging automatically +- Proper cleanup in destructors +- Device memory allocation through base framework + +### Threading +- Single-threaded main loop +- Vulkan command buffer recording on main thread +- UI rendering integrated with main render loop \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 3455a65d..00a0fcd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,13 +4,12 @@ cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") -set(NAME vulkanExamples) +set(NAME inihb) project(${NAME}) include_directories(external) include_directories(external/glm) -include_directories(external/gli) include_directories(external/imgui) include_directories(external/tinygltf) include_directories(external/ktx/include) @@ -179,4 +178,4 @@ ENDIF(WIN32) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/") add_subdirectory(base) -add_subdirectory(examples) +add_subdirectory(src) diff --git a/README.md b/README.md index 41a949cb..b21c505e 100644 --- a/README.md +++ b/README.md @@ -1,511 +1,197 @@ -# Vulkan C++ examples and demos +# Procedural 3D Engine -A comprehensive collection of open source C++ examples for [Vulkan®](https://www.vulkan.org), the low-level graphics and compute API from Khronos. - -[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BHXPMV6ZKPH9E) +A modern Vulkan-based 3D engine featuring procedural shape generation, scene management, and ImGui integration. Built on top of Sascha Willems' Vulkan examples framework with dynamic rendering support and C++20 standards. ## Table of Contents -+ [Official Khronos Vulkan Samples](#official-khronos-vulkan-samples) -+ [Cloning](#Cloning) -+ [Assets](#Assets) -+ [Building](#Building) -+ [Running](#Running) -+ [Shaders](#Shaders) -+ [A note on synchronization](#a-note-on-synchronization) -+ [Examples](#Examples) - + [Basics](#Basics) - + [glTF](#glTF) - + [Advanced](#Advanced) - + [Performance](#Performance) - + [Physically Based Rendering](#physically-based-rendering) - + [Deferred](#Deferred) - + [Compute Shader](#compute-shader) - + [Geometry Shader](#geometry-shader) - + [Tessellation Shader](#tessellation-shader) - + [Hardware accelerated ray tracing](#hardware-accelerated-ray-tracing) - + [Headless](#Headless) - + [User Interface](#user-interface) - + [Effects](#Effects) - + [Extensions](#Extensions) - + [Misc](#Misc) ++ [Features](#features) ++ [Requirements](#requirements) ++ [Building](#building) ++ [Running](#running) ++ [Architecture](#architecture) ++ [Camera System](#camera-system) ++ [Development](#development) ++ [Vulkan Examples](#vulkan-examples) + [Credits and Attributions](#credits-and-attributions) -## Official Khronos Vulkan Samples +## Features -Khronos has made an official Vulkan Samples repository available to the public ([press release](https://www.khronos.org/blog/vulkan-releases-unified-samples-repository?utm_source=Khronos%20Blog&utm_medium=Twitter&utm_campaign=Vulkan%20Repository)). +- **Modern Vulkan Rendering**: Built on Vulkan 1.3+ with dynamic rendering (VK_KHR_dynamic_rendering) +- **Procedural Shape Generation**: Generate and manipulate 3D shapes procedurally +- **Scene Management**: Hierarchical scene graph with object management +- **ImGui Integration**: Real-time UI for parameter adjustment and debugging +- **Advanced Camera System**: Orbit camera with focus functionality (F key) +- **Cross-Platform**: Windows, Linux, and macOS support +- **C++20 Standards**: Modern C++ codebase with latest language features -You can find this repository at https://github.com/KhronosGroup/Vulkan-Samples +## Requirements -As I've been involved with getting the official repository up and running, I'll be mostly contributing to that repository from now, but may still add samples that don't fit there in here and I'll of course continue to maintain these samples. +### Software Dependencies +- **Vulkan SDK** 1.3.0 or higher (required) +- **CMake** 3.10.0 or higher +- **C++20** compatible compiler: + - Visual Studio 2019/2022 (Windows) + - GCC 10+ or Clang 13+ (Linux) + - Xcode 13+ (macOS) -## Cloning -This repository contains submodules for external dependencies and assets, so when doing a fresh clone you need to clone recursively: - -``` -git clone --recursive https://github.com/SaschaWillems/Vulkan.git -``` - -Existing repositories can be updated manually: - -``` -git submodule init -git submodule update -``` +### Hardware Requirements +- Vulkan-compatible GPU +- 2GB+ VRAM recommended +- GPU with dynamic rendering support preferred ## Building -The repository contains everything required to compile and build the examples on Windows, Android, iOS and macOS (using MoltenVK) using a C++ compiler that supports C++20. +### Quick Build (All Platforms) +```bash +# From project root directory +mkdir build && cd build +cmake .. && cmake --build . --config Release +``` -See [BUILD.md](BUILD.md) for details on how to build for the different platforms. +### Platform-Specific Build + +#### Windows (Visual Studio) +```bash +mkdir build && cd build +cmake .. -G "Visual Studio 16 2019" -A x64 +cmake --build . --config Release +``` + +#### Linux +```bash +mkdir build && cd build +cmake .. && make -j$(nproc) +``` + +#### macOS +```bash +mkdir build && cd build +cmake .. && make -j$(sysctl -n hw.ncpu) +``` + +### Output Location +- **Executable**: `build/bin/Release/ProceduralEngine3D.exe` (Windows) or `build/bin/Release/ProceduralEngine3D` (Unix) +- **Assets**: Automatically copied to output directory + +For detailed build instructions, see [BUILD.md](BUILD.md). ## Running -Once built, examples can be run from the bin directory. The list of available command line options can be brought up with `--help`: +### Basic Usage +```bash +# From build output directory +cd build/bin/Release +./ProceduralEngine3D ``` - --help: Show help - -h, --height: Set window height - -v, --validation: Enable validation layers - -vs, --vsync: Enable V-Sync - -f, --fullscreen: Start in fullscreen mode - -w, --width: Set window width - -s, --shaders: Select shader type to use (glsl, slang, hlsl) - -g, --gpu: Select GPU to run on - -gl, --listgpus: Display a list of available Vulkan devices - -b, --benchmark: Run example in benchmark mode - -bw, --benchwarmup: Set warmup time for benchmark mode in seconds - -br, --benchruntime: Set duration time for benchmark mode in seconds - -bf, --benchfilename: Set file name for benchmark results - -bt, --benchframetimes: Save frame times to benchmark results file - -bfs, --benchmarkframes: Only render the given number of frames - -rp, --resourcepath: Set path for dir where assets and shaders folder is present + +### Command Line Options +Use `--help` to see all available options: +```bash +./ProceduralEngine3D --help ``` -Note that some examples require specific device features, and if you are on a multi-gpu system you might need to use the `-gl` and `-g` to select a gpu that supports them. -## Shaders - -Vulkan consumes shaders in an intermediate representation called SPIR-V. This makes it possible to use different shader languages by compiling them to that bytecode format. The primary shader language used here is [GLSL](shaders/glsl), most samples also come with [slang](shaders/slang/) and [HLSL](shaders/hlsl) shader sources, making it easy to compare the differences between those shading languages. The [Rust GPU](https://rust-gpu.github.io/) project maintains [Rust](https://www.rust-lang.org/) shader sources in a [separate repo](https://github.com/Rust-GPU/VulkanShaderExamples/tree/master/shaders/rust). - -## A note on synchronization - -Synchronization in the master branch currently isn't optimal und uses ```vkDeviceQueueWaitIdle``` at the end of each frame. This is a heavy operation and is suboptimal in regards to having CPU and GPU operations run in parallel. I'm currently reworking this in the [this branch](https://github.com/SaschaWillems/Vulkan/tree/sync_rework_second_attempt). While still work-in-progress, if you're interested in a more proper way of synchronization in Vulkan, please take a look at the [PR for that branch](https://github.com/SaschaWillems/Vulkan/pull/1224) to see progress. - -## Examples - -### Basics - -- [Basic triangle using Vulkan 1.0](examples/triangle/) - - Basic and verbose example for getting a colored triangle rendered to the screen using Vulkan. This is meant as a starting point for learning Vulkan from the ground up. A huge part of the code is boilerplate that is abstracted away in later examples. - -- [Basic triangle using Vulkan 1.3](examples/trianglevulkan13//) - - Vulkan 1.3 version of the basic and verbose example for getting a colored triangle rendered to the screen. This makes use of features like dynamic rendering simplifying api usage. - -- [Pipelines](examples/pipelines/) - - Using pipeline state objects (pso) that bake state information (rasterization states, culling modes, etc.) along with the shaders into a single object, making it easy for an implementation to optimize usage (compared to OpenGL's dynamic state machine). Also demonstrates the use of pipeline derivatives. - -- [Descriptor sets](examples/descriptorsets) - - Descriptors are used to pass data to shader binding points. Sets up descriptor sets, layouts, pools, creates a single pipeline based on the set layout and renders multiple objects with different descriptor sets. - -- [Dynamic uniform buffers](examples/dynamicuniformbuffer/) - - Dynamic uniform buffers are used for rendering multiple objects with multiple matrices stored in a single uniform buffer object. Individual matrices are dynamically addressed upon descriptor binding time, minimizing the number of required descriptor sets. - -- [Push constants](examples/pushconstants/) - - Uses push constants, small blocks of uniform data stored within a command buffer, to pass data to a shader without the need for uniform buffers. - -- [Specialization constants](examples/specializationconstants/) - - Uses SPIR-V specialization constants to create multiple pipelines with different lighting paths from a single "uber" shader. - -- [Texture mapping](examples/texture/) - - Loads a 2D texture from disk (including all mip levels), uses staging to upload it into video memory and samples from it using combined image samplers. - -- [Texture arrays](examples/texturearray/) - - Loads a 2D texture array containing multiple 2D texture slices (each with its own mip chain) and renders multiple meshes each sampling from a different layer of the texture. 2D texture arrays don't do any interpolation between the slices. - -- [Cube map textures](examples/texturecubemap/) - - Loads a cube map texture from disk containing six different faces. All faces and mip levels are uploaded into video memory, and the cubemap is displayed on a skybox as a backdrop and on a 3D model as a reflection. - -- [Cube map arrays](examples/texturecubemaparray/) - - Loads an array of cube map textures from a single file. All cube maps are uploaded into video memory with their faces and mip levels, and the selected cubemap is displayed on a skybox as a backdrop and on a 3D model as a reflection. - -- [3D textures](examples/texture3d/) - - Generates a 3D texture on the cpu (using perlin noise), uploads it to the device and samples it to render an animation. 3D textures store volumetric data and interpolate in all three dimensions. - -- [Input attachments](examples/inputattachments) - - Uses input attachments to read framebuffer contents from a previous sub pass at the same pixel position within a single render pass. This can be used for basic post processing or image composition ([blog entry](https://www.saschawillems.de/tutorials/vulkan/input_attachments_subpasses)). - -- [Sub passes](examples/subpasses/) - - Advanced example that uses sub passes and input attachments to write and read back data from framebuffer attachments (same location only) in single render pass. This is used to implement deferred render composition with added forward transparency in a single pass. - -- [Offscreen rendering](examples/offscreen/) - - Basic offscreen rendering in two passes. First pass renders the mirrored scene to a separate framebuffer with color and depth attachments, second pass samples from that color attachment for rendering a mirror surface. - -- [CPU particle system](examples/particlesystem/) - - Implements a simple CPU based particle system. Particle data is stored in host memory, updated on the CPU per-frame and synchronized with the device before it's rendered using pre-multiplied alpha. - -- [Stencil buffer](examples/stencilbuffer/) - - Uses the stencil buffer and its compare functionality for rendering a 3D model with dynamic outlines. - -- [Vertex attributes](examples/vertexattributes/) - - Demonstrates two different ways of passing vertices to the vertex shader using either interleaved or separate vertex attributes. - -### glTF - -These samples show how implement different features of the [glTF 2.0 3D format](https://www.khronos.org/gltf/) 3D transmission file format in detail. - -- [glTF model loading and rendering](examples/gltfloading/) - - Shows how to load a complete scene from a [glTF 2.0](https://github.com/KhronosGroup/glTF) file. The structure of the glTF 2.0 scene is converted into the data structures required to render the scene with Vulkan. - -- [glTF vertex skinning](examples/gltfskinning/) - - Demonstrates how to do GPU vertex skinning from animation data stored in a [glTF 2.0](https://github.com/KhronosGroup/glTF) model. Along with reading all the data structures required for doing vertex skinning, the sample also shows how to upload animation data to the GPU and how to render it using shaders. - -- [glTF scene rendering](examples/gltfscenerendering/) - - Renders a complete scene loaded from an [glTF 2.0](https://github.com/KhronosGroup/glTF) file. The sample is based on the glTF model loading sample, and adds data structures, functions and shaders required to render a more complex scene using Crytek's Sponza model with per-material pipelines and normal mapping. - -### Advanced - -- [Multi sampling](examples/multisampling/) - - Implements multisample anti-aliasing (MSAA) using a renderpass with multisampled attachments and resolve attachments that get resolved into the visible frame buffer. - -- [High dynamic range](examples/hdr/) - - Implements a high dynamic range rendering pipeline using 16/32 bit floating point precision for all internal formats, textures and calculations, including a bloom pass, manual exposure and tone mapping. - -- [Shadow mapping](examples/shadowmapping/) - - Rendering shadows for a directional light source. First pass stores depth values from the light's pov, second pass compares against these to check if a fragment is shadowed. Uses depth bias to avoid shadow artifacts and applies a PCF filter to smooth shadow edges. - -- [Cascaded shadow mapping](examples/shadowmappingcascade/) - - Uses multiple shadow maps (stored as a layered texture) to increase shadow resolution for larger scenes. The camera frustum is split up into multiple cascades with corresponding layers in the shadow map. Layer selection for shadowing depth compare is then done by comparing fragment depth with the cascades' depths ranges. - -- [Omnidirectional shadow mapping](examples/shadowmappingomni/) - - Uses a dynamic floating point cube map to implement shadowing for a point light source that casts shadows in all directions. The cube map is updated every frame and stores distance to the light source for each fragment used to determine if a fragment is shadowed. - -- [Run-time mip-map generation](examples/texturemipmapgen/) - - Generating a complete mip-chain at runtime instead of loading it from a file, by blitting from one mip level, starting with the actual texture image, down to the next smaller size until the lower 1x1 pixel end of the mip chain. - -- [Capturing screenshots](examples/screenshot/) - - Capturing and saving an image after a scene has been rendered using blits to copy the last swapchain image from optimal device to host local linear memory, so that it can be stored into a ppm image. - -- [Order Independent Transparency](examples/oit) - - Implements order independent transparency based on linked lists. To achieve this, the sample uses storage buffers in combination with image load and store atomic operations in the fragment shader. - -### Performance - -- [Multi threaded command buffer generation](examples/multithreading/) - - Multi threaded parallel command buffer generation. Instead of prebuilding and reusing the same command buffers this sample uses multiple hardware threads to demonstrate parallel per-frame recreation of secondary command buffers that are executed and submitted in a primary buffer once all threads have finished. - -- [Instancing](examples/instancing/) - - Uses the instancing feature for rendering many instances of the same mesh from a single vertex buffer with variable parameters and textures (indexing a layered texture). Instanced data is passed using a secondary vertex buffer. - -- [Indirect drawing](examples/indirectdraw/) - - Rendering thousands of instanced objects with different geometry using one single indirect draw call instead of issuing separate draws. All draw commands to be executed are stored in a dedicated indirect draw buffer object (storing index count, offset, instance count, etc.) that is uploaded to the device and sourced by the indirect draw command for rendering. - -- [Occlusion queries](examples/occlusionquery/) - - Using query pool objects to get number of passed samples for rendered primitives got determining on-screen visibility. - -- [Pipeline statistics](examples/pipelinestatistics/) - - Using query pool objects to gather statistics from different stages of the pipeline like vertex, fragment shader and tessellation evaluation shader invocations depending on payload. - -### Physically Based Rendering - -Physical based rendering as a lighting technique that achieves a more realistic and dynamic look by applying approximations of bidirectional reflectance distribution functions based on measured real-world material parameters and environment lighting. - -- [PBR basics](examples/pbrbasic/) - - Demonstrates a basic specular BRDF implementation with solid materials and fixed light sources on a grid of objects with varying material parameters, demonstrating how metallic reflectance and surface roughness affect the appearance of pbr lit objects. - -- [PBR image based lighting](examples/pbribl/) - - Adds image based lighting from an hdr environment cubemap to the PBR equation, using the surrounding environment as the light source. This adds an even more realistic look the scene as the light contribution used by the materials is now controlled by the environment. Also shows how to generate the BRDF 2D-LUT and irradiance and filtered cube maps from the environment map. - -- [Textured PBR with IBL](examples/pbrtexture/) - - Renders a model specially crafted for a metallic-roughness PBR workflow with textures defining material parameters for the PRB equation (albedo, metallic, roughness, baked ambient occlusion, normal maps) in an image based lighting environment. - -### Deferred - -These examples use a [deferred shading](https://en.wikipedia.org/wiki/Deferred_shading) setup. - -- [Deferred shading basics](examples/deferred/) - - Uses multiple render targets to fill all attachments (albedo, normals, position, depth) required for a G-Buffer in a single pass. A deferred pass then uses these to calculate shading and lighting in screen space, so that calculations only have to be done for visible fragments independent of no. of lights. - -- [Deferred multi sampling](examples/deferredmultisampling/) - - Adds multi sampling to a deferred renderer using manual resolve in the fragment shader. - -- [Deferred shading shadow mapping](examples/deferredshadows/) - - Adds shadows from multiple spotlights to a deferred renderer using a layered depth attachment filled in one pass using multiple geometry shader invocations. - -- [Screen space ambient occlusion](examples/ssao/) - - Adds ambient occlusion in screen space to a 3D scene. Depth values from a previous deferred pass are used to generate an ambient occlusion texture that is blurred before being applied to the scene in a final composition path. - -### Compute Shader - -All Vulkan implementations support compute shaders, a more generalized way of doing workloads on the GPU. These samples demonstrate how to use those compute shaders. - -- [Image processing](examples/computeshader/) - - Uses a compute shader along with a separate compute queue to apply different convolution kernels (and effects) on an input image in realtime. - -- [GPU particle system](examples/computeparticles/) - - Attraction based 2D GPU particle system using compute shaders. Particle data is stored in a shader storage buffer and only modified on the GPU using memory barriers for synchronizing compute particle updates with graphics pipeline vertex access. - -- [N-body simulation](examples/computenbody/) - - N-body simulation based particle system with multiple attractors and particle-to-particle interaction using two passes separating particle movement calculation and final integration. Shared compute shader memory is used to speed up compute calculations. - -- [Ray tracing](examples/computeraytracing/) - - Simple GPU ray tracer with shadows and reflections using a compute shader. No scene geometry is rendered in the graphics pass. - -- [ Cloth simulation](examples/computecloth/) - - Mass-spring based cloth system on the GPU using a compute shader to calculate and integrate spring forces, also implementing basic collision with a fixed scene object. - -- [Cull and LOD](examples/computecullandlod/) - - Purely GPU based frustum visibility culling and level-of-detail system. A compute shader is used to modify draw commands stored in an indirect draw commands buffer to toggle model visibility and select its level-of-detail based on camera distance, no calculations have to be done on and synced with the CPU. - -### Geometry Shader - -- [Normal debugging](examples/geometryshader/) - - Visualizing per-vertex model normals (for debugging). First pass renders the plain model, second pass uses a geometry shader to generate colored lines based on per-vertex model normals, - -- [Viewport arrays](examples/viewportarray/) - - Renders a scene to multiple viewports in one pass using a geometry shader to apply different matrices per viewport to simulate stereoscopic rendering (left/right). Requires a device with support for ```multiViewport```. - -### Tessellation Shader - -- [Displacement mapping](examples/displacement/) - - Uses a height map to dynamically generate and displace additional geometric detail for a low-poly mesh. - -- [Dynamic terrain tessellation](examples/terraintessellation/) - - Renders a terrain using tessellation shaders for height displacement (based on a 16-bit height map), dynamic level-of-detail (based on triangle screen space size) and per-patch frustum culling. - -- [Model tessellation](examples/tessellation/) - - Uses curved PN-triangles ([paper](http://alex.vlachos.com/graphics/CurvedPNTriangles.pdf)) for adding details to a low-polygon model. - -### Hardware accelerated ray tracing - -Vulkan supports GPUs with dedicated hardware for ray tracing. These sampples show different parts of that functionality. - -- [Basic ray tracing](examples/raytracingbasic) - - Basic example for doing hardware accelerated ray tracing using the ```VK_KHR_acceleration_structure``` and ```VK_KHR_ray_tracing_pipeline``` extensions. Shows how to setup acceleration structures, ray tracing pipelines and the shader binding table needed to do the actual ray tracing. - -- [Ray traced shadows](examples/raytracingshadows) - - Adds ray traced shadows casting using the new ray tracing extensions to a more complex scene. Shows how to add multiple hit and miss shaders and how to modify existing shaders to add shadow calculations. - -- [Ray traced reflections](examples/raytracingreflections) - - Renders a complex scene with reflective surfaces using the new ray tracing extensions. Shows how to do recursion inside of the ray tracing shaders for implementing real time reflections. - -- [Ray traced texture mapping](examples/raytracingtextures) - - Renders a texture mapped quad with transparency using the new ray tracing extensions. Shows how to do texture mapping in a closes hit shader, how to cancel intersections for transparency in an any hit shader and how to access mesh data in those shaders using buffer device addresses. - -- [Callable ray tracing shaders](examples/raytracingcallable) - - Callable shaders can be dynamically invoked from within other ray tracing shaders to execute different shaders based on dynamic conditions. The example ray traces multiple geometries, with each calling a different callable shader from the closest hit shader. - -- [Ray tracing intersection shaders](examples/raytracingintersection) - - Uses an intersection shader for procedural geometry. Instead of using actual geometry, this sample on passes bounding boxes and object definitions. An intersection shader is then used to trace against the procedural objects. - -- [Ray traced glTF](examples/raytracinggltf/) - - Renders a textured glTF model using ray traying instead of rasterization. Makes use of frame accumulation for transparency and anti aliasing. - -- [Ray query](examples/rayquery) - - Ray queries add acceleration structure intersection functionality to non ray tracing shader stages. This allows for combining ray tracing with rasterization. This example makes uses ray queries to add ray casted shadows to a rasterized sample in the fragment shader. - -- [Position fetch](examples/raytracingpositionfetch/) - - Uses the `VK_KHR_ray_tracing_position_fetch` extension to fetch vertex position data from the acceleration structure from within a shader, instead of having to manually unpack vertex information. - -### Headless - -Examples that run one-time tasks and don't make use of visual output (no window system integration). These can be run in environments where no user interface is available ([blog entry](https://www.saschawillems.de/tutorials/vulkan/headless_examples)). - -- [Render](examples/renderheadless) - - Renders a basic scene to a (non-visible) frame buffer attachment, reads it back to host memory and stores it to disk without any on-screen presentation, showing proper use of memory barriers required for device to host image synchronization. - -- [Compute](examples/computeheadless) - - Only uses compute shader capabilities for running calculations on an input data set (passed via SSBO). A fibonacci row is calculated based on input data via the compute shader, stored back and displayed via command line. - -### User Interface - -- [Text rendering](examples/textoverlay/) - - Load and render a 2D text overlay created from the bitmap glyph data of a [stb font file](https://nothings.org/stb/font/). This data is uploaded as a texture and used for displaying text on top of a 3D scene in a second pass. - -- [Distance field fonts](examples/distancefieldfonts/) - - Uses a texture that stores signed distance field information per character along with a special fragment shader calculating output based on that distance data. This results in crisp high quality font rendering independent of font size and scale. - -- [ImGui overlay](examples/imgui/) - - Generates and renders a complex user interface with multiple windows, controls and user interaction on top of a 3D scene. The UI is generated using [Dear ImGUI](https://github.com/ocornut/imgui) and updated each frame. - -### Extensions - -Vulkan is an extensible api with lots of functionality added by extensions. These samples demonstrate the usage of such extensions. - -**Note:** Certain extensions may become core functionality for newer Vulkan versions. The samples will still work with these. - -- [Conservative rasterization (VK_EXT_conservative_rasterization)](examples/conservativeraster/) - - Uses conservative rasterization to change the way fragments are generated by the gpu. The example enables overestimation to generate fragments for every pixel touched instead of only pixels that are fully covered ([blog post](https://www.saschawillems.de/tutorials/vulkan/conservative_rasterization)). - -- [Push descriptors (VK_KHR_push_descriptor)](examples/pushdescriptors/) - - Uses push descriptors apply the push constants concept to descriptor sets. Instead of creating per-object descriptor sets for rendering multiple objects, this example passes descriptors at command buffer creation time. - -- [Inline uniform blocks (VK_EXT_inline_uniform_block)](examples/inlineuniformblocks/) - - Makes use of inline uniform blocks to pass uniform data directly at descriptor set creation time and also demonstrates how to update data for those descriptors at runtime. - -- [Multiview rendering (VK_KHR_multiview)](examples/multiview/) - - Renders a scene to to multiple views (layers) of a single framebuffer to simulate stereoscopic rendering in one pass. Broadcasting to the views is done in the vertex shader using ```gl_ViewIndex```. - -- [Conditional rendering (VK_EXT_conditional_rendering)](examples/conditionalrender) - - Demonstrates the use of VK_EXT_conditional_rendering to conditionally dispatch render commands based on values from a dedicated buffer. This allows e.g. visibility toggles without having to rebuild command buffers ([blog post](https://www.saschawillems.de/tutorials/vulkan/conditional_rendering)). - -- [Debug shader printf (VK_KHR_shader_non_semantic_info)](examples/debugprintf/) - - Shows how to use printf in a shader to output additional information per invocation. This information can help debugging shader related issues in tools like RenderDoc. - - **Note:** This sample should be run from a graphics debugger like RenderDoc. - -- [Debug utils (VK_EXT_debug_utils)](examples/debugutils/) - - Shows how to use debug utils for adding labels and colors to Vulkan objects for graphics debuggers. This information helps to identify resources in tools like RenderDoc. - - **Note:** This sample should be run from a graphics debugger like RenderDoc. - -- [Negative viewport height (VK_KHR_Maintenance1 or Vulkan 1.1)](examples/negativeviewportheight/) - - Shows how to render a scene using a negative viewport height, making the Vulkan render setup more similar to other APIs like OpenGL. Also has several options for changing relevant pipeline state, and displaying meshes with OpenGL or Vulkan style coordinates. Details can be found in [this tutorial](https://www.saschawillems.de/tutorials/vulkan/flipping-viewport). - -- [Variable rate shading (VK_KHR_fragment_shading_rate)](examples/variablerateshading/) - - Uses a special image that contains variable shading rates to vary the number of fragment shader invocations across the framebuffer. This makes it possible to lower fragment shader invocations for less important/less noisy parts of the framebuffer. - -- [Descriptor indexing (VK_EXT_descriptor_indexing)](examples/descriptorindexing/) - - Demonstrates the use of VK_EXT_descriptor_indexing for creating descriptor sets with a variable size that can be dynamically indexed in a shader using `GL_EXT_nonuniform_qualifier` and `SPV_EXT_descriptor_indexing`. - -- [Dynamic rendering (VK_KHR_dynamic_rendering)](examples/dynamicrendering/) - - Shows usage of the VK_KHR_dynamic_rendering extension, which simplifies the rendering setup by no longer requiring render pass objects or framebuffers. - -- [Dynamic rendering with multi sampling (VK_KHR_dynamic_rendering)](examples/dynamicrenderingmultisampling/) - - Based on the dynamic rendering sample, this sample shows how to do implement multi sampling with dynamic rendering. - -- [Graphics pipeline library (VK_EXT_graphics_pipeline_library)](./examples/graphicspipelinelibrary) - - Uses the graphics pipeline library extensions to improve run-time pipeline creation. Instead of creating the whole pipeline at once, this sample pre builds shared pipeline parts like like vertex input state and fragment output state. These are then used to create full pipelines at runtime, reducing build times and possible hick-ups. - -- [Mesh shaders (VK_EXT_mesh_shader)](./examples/meshshader) - - Basic sample demonstrating how to use the mesh shading pipeline as a replacement for the traditional vertex pipeline. - -- [Descriptor buffers (VK_EXT_descriptor_buffer)](./examples/descriptorbuffer/) - - Basic sample showing how to use descriptor buffers to replace descriptor sets. - -- [Shader objects (VK_EXT_shader_object)](./examples/shaderobjects/) - - Basic sample showing how to use shader objects that can be used to replace pipeline state objects. Instead of baking all state in a PSO, shaders are explicitly loaded and bound as separate objects and state is set using dynamic state extensions. The sample also stores binary shader objets and loads them on consecutive runs. - -- [Host image copy (VK_EXT_host_image_copy)](./examples/hostimagecopy/) - - Shows how to do host image copies, which heavily simplify the host to device image process by fully skipping the staging process. - -- [Buffer device address (VK_KHR_buffer_device_addres)](./examples/bufferdeviceaddress/) - - Demonstrates the use of virtual GPU addresses to directly access buffer data in shader. Instead of e.g. using descriptors to access uniforms, with this extension you simply provide an address to the memory you want to read from in the shader and that address can be arbitrarily changed e.g. via a push constant. - -- [Timeline semaphores (VK_KHR_timeline_semaphore)](./examples/timelinesemaphore/) - - Shows how to use a new semaphore type that has a way of setting and identifying a given point on a timeline. Compared to the core binary semaphores, this simplifies synchronization as a single timeline semaphore can replace multiple binary semaphores. - -### Effects - -Assorted samples showing graphical effects not special to Vulkan. - -- [Fullscreen radial blur](examples/radialblur/) - - Demonstrates the basics of fullscreen shader effects. The scene is rendered into an offscreen framebuffer at lower resolution and rendered as a fullscreen quad atop the scene using a radial blur fragment shader. - -- [Bloom](examples/bloom/) - - Advanced fullscreen effect example adding a bloom effect to a scene. Glowing scene parts are rendered to a low res offscreen framebuffer that is applied atop the scene using a two pass separated gaussian blur. - -- [Parallax mapping](examples/parallaxmapping/) - - Implements multiple texture mapping methods to simulate depth based on texture information: Normal mapping, parallax mapping, steep parallax mapping and parallax occlusion mapping (best quality, worst performance). - -- [Spherical environment mapping](examples/sphericalenvmapping/) - - Uses a spherical material capture texture array defining environment lighting and reflection information to fake complex lighting. - -### Misc - -- [Vulkan Gears](examples/gears/) - - Vulkan interpretation of glxgears. Procedurally generates and animates multiple gears. - -- [Vulkan demo scene](examples/vulkanscene/) - - Renders a Vulkan demo scene with logos and mascots. Not an actual example but more of a playground and showcase. +**Common Options:** +- `-v, --validation`: Enable Vulkan validation layers (recommended for development) +- `-w, --width`: Set window width (default: 1920) +- `-h, --height`: Set window height (default: 1080) +- `-f, --fullscreen`: Start in fullscreen mode +- `-g, --gpu`: Select specific GPU device +- `--listgpus`: Display available Vulkan devices + +### Controls +- **Mouse**: Look around (standard mode) or orbit (after F key focus) +- **WASD**: Move camera +- **F**: Focus camera on selected object +- **Mouse Wheel**: Zoom (in orbit mode changes distance) +- **ImGui panels**: Adjust parameters and debug information + +**Note**: Multi-GPU systems may require using `--listgpus` and `-g` to select a compatible device. + +## Architecture + +### Core Systems +- **Application Core** (`src/core/Application.cpp`): Main Vulkan application class inheriting from VulkanExampleBase +- **Scene Management** (`src/scene/`): Hierarchical scene graph and object management +- **UI System** (`src/ui/`): ImGui-based interface with real-time parameter adjustment +- **Camera System** (`base/camera.hpp`): Advanced orbit camera with focus functionality +- **Base Framework** (`base/`): Sascha Willems' Vulkan infrastructure + +### Vulkan Features +- **Dynamic Rendering**: Uses VK_KHR_dynamic_rendering (no render passes/framebuffers) +- **Modern API Usage**: Vulkan 1.3+ practices with timeline semaphores +- **Multi-platform**: Window system integration for Windows, Linux, macOS +- **Validation Support**: Comprehensive debugging with validation layers + +### Project Structure +``` +├── src/ # Engine source code +│ ├── core/ # Core application classes +│ ├── scene/ # Scene management +│ └── ui/ # ImGui interface +├── base/ # Vulkan base framework +├── shaders/glsl/ # GLSL shader sources +├── assets/ # 3D models and textures +└── build/ # Build output directory +``` + +## Camera System + +### F Key Focus Feature +The camera system supports advanced focusing functionality: +- **Press F**: Focus camera on selected object +- **Automatic Distance**: Calculates optimal viewing distance +- **Orbit Mode**: Mouse rotation orbits around focused object center +- **Hybrid System**: Combines standard camera with orbit mode using `glm::lookAt()` + +### Implementation +- `camera.focusOnObject()`: Sets orbit center and optimal distance +- `camera.updateOrbitPosition()`: Handles spherical coordinate positioning +- Seamless switching between standard and orbit modes + +## Development + +### Testing Changes +```bash +# Build and test +cd build +cmake --build . --config Release +bin/Release/ProceduralEngine3D -v # Enable validation layers +``` + +### Debugging +- Use `-v` flag for Vulkan validation layers +- Check console output for debug information +- Use `--listgpus` to verify device support +- ImGui panels provide real-time debugging information + +### Adding Features +- Follow Sascha Willems patterns for Vulkan code +- Use dynamic rendering (no render passes required) +- Implement proper buffer management and synchronization +- Add ImGui panels for new feature parameters + +## Vulkan Examples + +This engine is built on top of Sascha Willems' comprehensive Vulkan examples. While the main engine focuses on procedural generation and scene management, the original examples remain available for learning Vulkan concepts. + +### Available Examples +The `examples/` directory contains over 100 Vulkan examples covering: + +- **Basics**: Triangle rendering, pipelines, descriptor sets, textures +- **Advanced Rendering**: Shadow mapping, deferred shading, PBR, ray tracing +- **Compute Shaders**: GPU particles, N-body simulation, image processing +- **Modern Features**: Dynamic rendering, mesh shaders, descriptor buffers +- **Extensions**: Conservative rasterization, variable rate shading, timeline semaphores + +### Official Khronos Samples +For the most up-to-date Vulkan learning resources, also check the official Khronos Vulkan Samples repository at: https://github.com/KhronosGroup/Vulkan-Samples + +### Building Individual Examples +```bash +# Build specific example (from build directory) +cmake --build . --target triangle --config Release +``` + +For a complete reference of all available examples with detailed descriptions, see the original Sascha Willems Vulkan repository documentation. Each example demonstrates specific Vulkan concepts and can be built individually using the CMake targets. ## Credits and Attributions See [CREDITS.md](CREDITS.md) for additional credits and attributions. diff --git a/android/.gitignore b/android/.gitignore deleted file mode 100644 index f3fc352a..00000000 --- a/android/.gitignore +++ /dev/null @@ -1,69 +0,0 @@ -# Built application files -*.apk -*.ap_ - -# Files for the ART/Dalvik VM -*.dex - -# Java class files -*.class - -# Generated files -bin/ -gen/ -out/ - -# Gradle files -.gradle/ -build/ - -# Local configuration file (sdk path, etc) -local.properties - -# Proguard folder generated by Eclipse -proguard/ - -# Log Files -*.log - -# Android Studio Navigation editor temp files -.navigation/ - -# Android Studio captures folder -captures/ - -# IntelliJ -*.iml -.idea/workspace.xml -.idea/tasks.xml -.idea/gradle.xml -.idea/assetWizardSettings.xml -.idea/dictionaries -.idea/libraries -.idea/caches - -# Keystore files -# Uncomment the following line if you do not want to check your keystore files in. -#*.jks - -# External native build folder generated in Android Studio 2.2 and later -.externalNativeBuild - -# Google Services (e.g. APIs or Firebase) -google-services.json - -# Freeline -freeline.py -freeline/ -freeline_project_description.json - -# fastlane -fastlane/report.xml -fastlane/Preview.html -fastlane/screenshots -fastlane/test_output -fastlane/readme.md - -**/assets/ -**/src/main/res/drawable/ -**/.cxx/ \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle deleted file mode 100644 index c774fed5..00000000 --- a/android/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -/** Top-level build file where you can add configuration options common to all sub-projects/modules */ - -buildscript { - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:8.7.0' - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - mavenCentral() - } - // This code is where all the magic happens and fixes the error. - subprojects { - afterEvaluate { project -> - if (project.hasProperty('android')) { - project.android { - if (namespace == null) { - namespace "de.saschawillems." + project.group - } - } - } - } - } -} - -ext { - abiFilters = "arm64-v8a" - minSdkVersion = 21 - targetSdkVersion = 26 - compileSdkVersion = 26 - shaderPath = '../../../shaders/' - assetPath = '../../../assets/' -} \ No newline at end of file diff --git a/android/common/res/drawable/icon.png b/android/common/res/drawable/icon.png deleted file mode 100644 index 882f2a59..00000000 Binary files a/android/common/res/drawable/icon.png and /dev/null differ diff --git a/android/examples/_template/CMakeLists.txt b/android/examples/_template/CMakeLists.txt deleted file mode 100644 index 3411e789..00000000 --- a/android/examples/_template/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME %EXAMPLE_FOLDER%) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/_template/build.gradle b/android/examples/_template/build.gradle deleted file mode 100644 index ff28692a..00000000 --- a/android/examples/_template/build.gradle +++ /dev/null @@ -1,54 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.%PACKAGE_NAME%" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - -%ASSET_COPY% -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/_template/src/main/AndroidManifest.xml b/android/examples/_template/src/main/AndroidManifest.xml deleted file mode 100644 index d6b2ae8e..00000000 --- a/android/examples/_template/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/_template/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/_template/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/_template/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/base/CMakeLists.txt b/android/examples/base/CMakeLists.txt deleted file mode 100644 index e564d522..00000000 --- a/android/examples/base/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -file(GLOB BASE_SRC "../../../base/*.cpp" "../../../external/imgui/*.cpp") - -add_library(libbase SHARED ${BASE_SRC}) - -include_directories(${BASE_DIR}) -include_directories(../../../external) -include_directories(../../../external/glm) -include_directories(../../../external/gli) -include_directories(../../../external/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -set(KTX_DIR ../../../external/ktx) -set(KTX_SOURCES - ${KTX_DIR}/lib/texture.c - ${KTX_DIR}/lib/hashlist.c - ${KTX_DIR}/lib/checkheader.c - ${KTX_DIR}/lib/swap.c - ${KTX_DIR}/lib/memstream.c - ${KTX_DIR}/lib/filestream.c - ${KTX_DIR}/lib/vkloader.c -) -set(KTX_INCLUDE - ${KTX_DIR}/include - ${KTX_DIR}/lib - ${KTX_DIR}/other_include -) - -add_library(libktx ${KTX_SOURCES}) -target_include_directories(libktx PUBLIC ${KTX_INCLUDE}) -set_property(TARGET libktx PROPERTY FOLDER "external") - - -target_link_libraries( - libbase - android - log - z - libktx -) diff --git a/android/examples/bloom/CMakeLists.txt b/android/examples/bloom/CMakeLists.txt deleted file mode 100644 index ac3ec0e5..00000000 --- a/android/examples/bloom/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME bloom) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/bloom/build.gradle b/android/examples/bloom/build.gradle deleted file mode 100644 index 17ddb414..00000000 --- a/android/examples/bloom/build.gradle +++ /dev/null @@ -1,84 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanBloom" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath +'glsl/bloom' - into 'assets/shaders/glsl/bloom' - include '*.*' - } - - copy { - from rootProject.ext.assetPath +'models' - into 'assets/models' - include 'retroufo.gltf' - } - - copy { - from rootProject.ext.assetPath +'models' - into 'assets/models' - include 'retroufo_glow.gltf' - } - - copy { - from rootProject.ext.assetPath +'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'cubemap_space.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/bloom/src/main/AndroidManifest.xml b/android/examples/bloom/src/main/AndroidManifest.xml deleted file mode 100644 index 233f0056..00000000 --- a/android/examples/bloom/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/bloom/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/bloom/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/bloom/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/bufferdeviceaddress/CMakeLists.txt b/android/examples/bufferdeviceaddress/CMakeLists.txt deleted file mode 100644 index 4f4a35e6..00000000 --- a/android/examples/bufferdeviceaddress/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME bufferdeviceaddress) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/bufferdeviceaddress/build.gradle b/android/examples/bufferdeviceaddress/build.gradle deleted file mode 100644 index 9fe9a2af..00000000 --- a/android/examples/bufferdeviceaddress/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanBufferDeviceAddress" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/bufferdeviceaddress' - into 'assets/shaders/glsl/bufferdeviceaddress' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'crate01_color_height_rgba.ktx' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/bufferdeviceaddress/src/main/AndroidManifest.xml b/android/examples/bufferdeviceaddress/src/main/AndroidManifest.xml deleted file mode 100644 index cbc8668f..00000000 --- a/android/examples/bufferdeviceaddress/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/bufferdeviceaddress/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/bufferdeviceaddress/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/bufferdeviceaddress/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/computecloth/CMakeLists.txt b/android/examples/computecloth/CMakeLists.txt deleted file mode 100644 index 0b801305..00000000 --- a/android/examples/computecloth/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME computecloth) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/computecloth/build.gradle b/android/examples/computecloth/build.gradle deleted file mode 100644 index a51092fb..00000000 --- a/android/examples/computecloth/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanComputecloth" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/computecloth' - into 'assets/shaders/glsl/computecloth' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'vulkan_cloth_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/computecloth/src/main/AndroidManifest.xml b/android/examples/computecloth/src/main/AndroidManifest.xml deleted file mode 100644 index 859de434..00000000 --- a/android/examples/computecloth/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/computecloth/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/computecloth/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/computecloth/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/computecullandlod/CMakeLists.txt b/android/examples/computecullandlod/CMakeLists.txt deleted file mode 100644 index 1bdf0390..00000000 --- a/android/examples/computecullandlod/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME computecullandlod) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/computecullandlod/build.gradle b/android/examples/computecullandlod/build.gradle deleted file mode 100644 index 173bb056..00000000 --- a/android/examples/computecullandlod/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanComputecullandlod" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/computecullandlod' - into 'assets/shaders/glsl/computecullandlod' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'suzanne_lods.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/computecullandlod/src/main/AndroidManifest.xml b/android/examples/computecullandlod/src/main/AndroidManifest.xml deleted file mode 100644 index 9e85ce96..00000000 --- a/android/examples/computecullandlod/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/computecullandlod/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/computecullandlod/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/computecullandlod/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/computeheadless/CMakeLists.txt b/android/examples/computeheadless/CMakeLists.txt deleted file mode 100644 index 4b88223b..00000000 --- a/android/examples/computeheadless/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME computeheadless) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/computeheadless/build.gradle b/android/examples/computeheadless/build.gradle deleted file mode 100644 index 1c68bdcf..00000000 --- a/android/examples/computeheadless/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanComputeheadless" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/computeheadless' - into 'assets/shaders/glsl/computeheadless' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/computeheadless/src/main/AndroidManifest.xml b/android/examples/computeheadless/src/main/AndroidManifest.xml deleted file mode 100644 index da1e42b2..00000000 --- a/android/examples/computeheadless/src/main/AndroidManifest.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/android/examples/computeheadless/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/computeheadless/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/computeheadless/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/computenbody/CMakeLists.txt b/android/examples/computenbody/CMakeLists.txt deleted file mode 100644 index a4898de9..00000000 --- a/android/examples/computenbody/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME computenbody) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/computenbody/build.gradle b/android/examples/computenbody/build.gradle deleted file mode 100644 index 73ec7863..00000000 --- a/android/examples/computenbody/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanComputenbody" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/computenbody' - into 'assets/shaders/glsl/computenbody' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'particle01_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'particle_gradient_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/computenbody/src/main/AndroidManifest.xml b/android/examples/computenbody/src/main/AndroidManifest.xml deleted file mode 100644 index ccc07122..00000000 --- a/android/examples/computenbody/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/computenbody/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/computenbody/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/computenbody/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/computeparticles/CMakeLists.txt b/android/examples/computeparticles/CMakeLists.txt deleted file mode 100644 index 0a0255ff..00000000 --- a/android/examples/computeparticles/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME computeparticles) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/computeparticles/build.gradle b/android/examples/computeparticles/build.gradle deleted file mode 100644 index 58d054a7..00000000 --- a/android/examples/computeparticles/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanComputeparticles" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/computeparticles' - into 'assets/shaders/glsl/computeparticles' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'particle01_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'particle_gradient_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/computeparticles/src/main/AndroidManifest.xml b/android/examples/computeparticles/src/main/AndroidManifest.xml deleted file mode 100644 index e7614e10..00000000 --- a/android/examples/computeparticles/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/computeparticles/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/computeparticles/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/computeparticles/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/computeraytracing/CMakeLists.txt b/android/examples/computeraytracing/CMakeLists.txt deleted file mode 100644 index 801d15dd..00000000 --- a/android/examples/computeraytracing/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME computeraytracing) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/computeraytracing/build.gradle b/android/examples/computeraytracing/build.gradle deleted file mode 100644 index dd75ddc7..00000000 --- a/android/examples/computeraytracing/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanComputeRaytracing" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/computeraytracing' - into 'assets/shaders/glsl/computeraytracing' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/computeraytracing/src/main/AndroidManifest.xml b/android/examples/computeraytracing/src/main/AndroidManifest.xml deleted file mode 100644 index 9286fa3d..00000000 --- a/android/examples/computeraytracing/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/computeraytracing/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/computeraytracing/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/computeraytracing/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/computeshader/CMakeLists.txt b/android/examples/computeshader/CMakeLists.txt deleted file mode 100644 index 688dd589..00000000 --- a/android/examples/computeshader/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME computeshader) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/computeshader/build.gradle b/android/examples/computeshader/build.gradle deleted file mode 100644 index 4fe97915..00000000 --- a/android/examples/computeshader/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanComputeshader" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/computeshader' - into 'assets/shaders/glsl/computeshader' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'vulkan_11_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/computeshader/src/main/AndroidManifest.xml b/android/examples/computeshader/src/main/AndroidManifest.xml deleted file mode 100644 index dbb77b9f..00000000 --- a/android/examples/computeshader/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/computeshader/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/computeshader/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/computeshader/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/conditionalrender/CMakeLists.txt b/android/examples/conditionalrender/CMakeLists.txt deleted file mode 100644 index bca54576..00000000 --- a/android/examples/conditionalrender/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME conditionalrender) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/conditionalrender/build.gradle b/android/examples/conditionalrender/build.gradle deleted file mode 100644 index 725a46f6..00000000 --- a/android/examples/conditionalrender/build.gradle +++ /dev/null @@ -1,64 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanConditionalrender" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/conditionalrender' - into 'assets/shaders/glsl/conditionalrender' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models/gltf/glTF-Embedded' - into 'assets/models/gltf/glTF-Embedded' - include 'Buggy.gltf' - } -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/conditionalrender/src/main/AndroidManifest.xml b/android/examples/conditionalrender/src/main/AndroidManifest.xml deleted file mode 100644 index 3ab90a77..00000000 --- a/android/examples/conditionalrender/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/conditionalrender/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/conditionalrender/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/conditionalrender/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/conservativeraster/CMakeLists.txt b/android/examples/conservativeraster/CMakeLists.txt deleted file mode 100644 index 70705814..00000000 --- a/android/examples/conservativeraster/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME conservativeraster) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/conservativeraster/build.gradle b/android/examples/conservativeraster/build.gradle deleted file mode 100644 index b7abf2af..00000000 --- a/android/examples/conservativeraster/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanConservativeraster" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/conservativeraster' - into 'assets/shaders/glsl/conservativeraster' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/conservativeraster/src/main/AndroidManifest.xml b/android/examples/conservativeraster/src/main/AndroidManifest.xml deleted file mode 100644 index e9daac07..00000000 --- a/android/examples/conservativeraster/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/conservativeraster/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/conservativeraster/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/conservativeraster/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/debugprintf/CMakeLists.txt b/android/examples/debugprintf/CMakeLists.txt deleted file mode 100644 index 5ce8a32e..00000000 --- a/android/examples/debugprintf/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME debugprintf) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/debugprintf/build.gradle b/android/examples/debugprintf/build.gradle deleted file mode 100644 index 9a98a61c..00000000 --- a/android/examples/debugprintf/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDebugprintf" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/debugprintf' - into 'assets/shaders/glsl/debugprintf' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'treasure_smooth.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/debugprintf/src/main/AndroidManifest.xml b/android/examples/debugprintf/src/main/AndroidManifest.xml deleted file mode 100644 index bfb99c12..00000000 --- a/android/examples/debugprintf/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/debugprintf/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/debugprintf/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/debugprintf/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/debugutils/CMakeLists.txt b/android/examples/debugutils/CMakeLists.txt deleted file mode 100644 index 48ba3a6f..00000000 --- a/android/examples/debugutils/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME debugutils) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/debugutils/build.gradle b/android/examples/debugutils/build.gradle deleted file mode 100644 index b2a29b0a..00000000 --- a/android/examples/debugutils/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDebugutils" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/debugutils' - into 'assets/shaders/glsl/debugutils' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'treasure_smooth.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'treasure_glow.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/debugutils/src/main/AndroidManifest.xml b/android/examples/debugutils/src/main/AndroidManifest.xml deleted file mode 100644 index cdd22d06..00000000 --- a/android/examples/debugutils/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/debugutils/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/debugutils/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/debugutils/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/deferred/CMakeLists.txt b/android/examples/deferred/CMakeLists.txt deleted file mode 100644 index 2f9aa0ff..00000000 --- a/android/examples/deferred/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME deferred) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/deferred/build.gradle b/android/examples/deferred/build.gradle deleted file mode 100644 index 46226069..00000000 --- a/android/examples/deferred/build.gradle +++ /dev/null @@ -1,84 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDeferred" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/deferred' - into 'assets/shaders/glsl/deferred' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'deferred_floor.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'stonefloor01_color_*.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'stonefloor01_normal_*.ktx' - } - - copy { - from rootProject.ext.assetPath + 'models/armor' - into 'assets/models/armor' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/deferred/src/main/AndroidManifest.xml b/android/examples/deferred/src/main/AndroidManifest.xml deleted file mode 100644 index b1838c4a..00000000 --- a/android/examples/deferred/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/deferred/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/deferred/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/deferred/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/deferredmultisampling/CMakeLists.txt b/android/examples/deferredmultisampling/CMakeLists.txt deleted file mode 100644 index 9c01e50f..00000000 --- a/android/examples/deferredmultisampling/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME deferredmultisampling) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/deferredmultisampling/build.gradle b/android/examples/deferredmultisampling/build.gradle deleted file mode 100644 index 4d08713e..00000000 --- a/android/examples/deferredmultisampling/build.gradle +++ /dev/null @@ -1,84 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDeferredmultisampling" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/deferredmultisampling' - into 'assets/shaders/glsl/deferredmultisampling' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'deferred_box.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'stonefloor02_color_*.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'stonefloor02_normal_*.ktx' - } - - copy { - from rootProject.ext.assetPath + 'models/armor' - into 'assets/models/armor' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/deferredmultisampling/src/main/AndroidManifest.xml b/android/examples/deferredmultisampling/src/main/AndroidManifest.xml deleted file mode 100644 index 49426468..00000000 --- a/android/examples/deferredmultisampling/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/deferredmultisampling/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/deferredmultisampling/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/deferredmultisampling/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/deferredshadows/CMakeLists.txt b/android/examples/deferredshadows/CMakeLists.txt deleted file mode 100644 index 8523380e..00000000 --- a/android/examples/deferredshadows/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME deferredshadows) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/deferredshadows/build.gradle b/android/examples/deferredshadows/build.gradle deleted file mode 100644 index 76ad5f81..00000000 --- a/android/examples/deferredshadows/build.gradle +++ /dev/null @@ -1,84 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDeferredshadows" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/deferredshadows' - into 'assets/shaders/glsl/deferredshadows' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'deferred_box.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'stonefloor02_color_*.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'stonefloor02_normal_*.ktx' - } - - copy { - from rootProject.ext.assetPath + 'models/armor' - into 'assets/models/armor' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/deferredshadows/src/main/AndroidManifest.xml b/android/examples/deferredshadows/src/main/AndroidManifest.xml deleted file mode 100644 index cdb0a40f..00000000 --- a/android/examples/deferredshadows/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/deferredshadows/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/deferredshadows/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/deferredshadows/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/descriptorbuffer/CMakeLists.txt b/android/examples/descriptorbuffer/CMakeLists.txt deleted file mode 100644 index 8b1f3694..00000000 --- a/android/examples/descriptorbuffer/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME descriptorbuffer) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/descriptorbuffer/build.gradle b/android/examples/descriptorbuffer/build.gradle deleted file mode 100644 index 54ae5720..00000000 --- a/android/examples/descriptorbuffer/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDescriptorbuffer" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/descriptorbuffer' - into 'assets/shaders/glsl/descriptorbuffer' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'crate01_color_height_rgba.gltf' - include 'crate02_color_height_rgba.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/descriptorbuffer/src/main/AndroidManifest.xml b/android/examples/descriptorbuffer/src/main/AndroidManifest.xml deleted file mode 100644 index 7f1039fb..00000000 --- a/android/examples/descriptorbuffer/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/descriptorbuffer/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/descriptorbuffer/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/descriptorbuffer/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/descriptorindexing/CMakeLists.txt b/android/examples/descriptorindexing/CMakeLists.txt deleted file mode 100644 index 69a813ea..00000000 --- a/android/examples/descriptorindexing/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME descriptorindexing) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/descriptorindexing/build.gradle b/android/examples/descriptorindexing/build.gradle deleted file mode 100644 index a56ebce4..00000000 --- a/android/examples/descriptorindexing/build.gradle +++ /dev/null @@ -1,58 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDescriptorindexing" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/descriptorindexing' - into 'assets/shaders/glsl/descriptorindexing' - include '*.*' - } -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/descriptorindexing/src/main/AndroidManifest.xml b/android/examples/descriptorindexing/src/main/AndroidManifest.xml deleted file mode 100644 index a85c1566..00000000 --- a/android/examples/descriptorindexing/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/descriptorindexing/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/descriptorindexing/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/descriptorindexing/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/descriptorsets/CMakeLists.txt b/android/examples/descriptorsets/CMakeLists.txt deleted file mode 100644 index 639667ea..00000000 --- a/android/examples/descriptorsets/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME descriptorsets) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/descriptorsets/build.gradle b/android/examples/descriptorsets/build.gradle deleted file mode 100644 index 7ea2181b..00000000 --- a/android/examples/descriptorsets/build.gradle +++ /dev/null @@ -1,78 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDescriptorsets" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/descriptorsets' - into 'assets/shaders/glsl/descriptorsets' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'crate01_color_height_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'crate02_color_height_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/descriptorsets/src/main/AndroidManifest.xml b/android/examples/descriptorsets/src/main/AndroidManifest.xml deleted file mode 100644 index 0dac572e..00000000 --- a/android/examples/descriptorsets/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/descriptorsets/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/descriptorsets/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/descriptorsets/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/displacement/CMakeLists.txt b/android/examples/displacement/CMakeLists.txt deleted file mode 100644 index 300c9dd4..00000000 --- a/android/examples/displacement/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME displacement) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/displacement/build.gradle b/android/examples/displacement/build.gradle deleted file mode 100644 index 0cd19008..00000000 --- a/android/examples/displacement/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDisplacement" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/displacement' - into 'assets/shaders/glsl/displacement' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'displacement_plane.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'stonefloor03_color_height_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/displacement/src/main/AndroidManifest.xml b/android/examples/displacement/src/main/AndroidManifest.xml deleted file mode 100644 index 3b6ca22b..00000000 --- a/android/examples/displacement/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/displacement/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/displacement/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/displacement/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/distancefieldfonts/CMakeLists.txt b/android/examples/distancefieldfonts/CMakeLists.txt deleted file mode 100644 index 7694a122..00000000 --- a/android/examples/distancefieldfonts/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME distancefieldfonts) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/distancefieldfonts/build.gradle b/android/examples/distancefieldfonts/build.gradle deleted file mode 100644 index 8dc4bb04..00000000 --- a/android/examples/distancefieldfonts/build.gradle +++ /dev/null @@ -1,78 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDistancefieldfonts" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/distancefieldfonts' - into 'assets/shaders/glsl/distancefieldfonts' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'font_sdf_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'font_bitmap_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + './' - into 'assets/./' - include 'font.fnt' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/distancefieldfonts/src/main/AndroidManifest.xml b/android/examples/distancefieldfonts/src/main/AndroidManifest.xml deleted file mode 100644 index 2a844fd4..00000000 --- a/android/examples/distancefieldfonts/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/distancefieldfonts/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/distancefieldfonts/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/distancefieldfonts/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/dynamicrendering/CMakeLists.txt b/android/examples/dynamicrendering/CMakeLists.txt deleted file mode 100644 index 0611870c..00000000 --- a/android/examples/dynamicrendering/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME dynamicrendering) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/dynamicrendering/build.gradle b/android/examples/dynamicrendering/build.gradle deleted file mode 100644 index 70825b84..00000000 --- a/android/examples/dynamicrendering/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDynamicrendering" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/dynamicrendering' - into 'assets/shaders/glsl/dynamicrendering' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'voyager.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/dynamicrendering/src/main/AndroidManifest.xml b/android/examples/dynamicrendering/src/main/AndroidManifest.xml deleted file mode 100644 index d6c17910..00000000 --- a/android/examples/dynamicrendering/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/dynamicrendering/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/dynamicrendering/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/dynamicrendering/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/dynamicrenderingmultisampling/CMakeLists.txt b/android/examples/dynamicrenderingmultisampling/CMakeLists.txt deleted file mode 100644 index 256b5b4f..00000000 --- a/android/examples/dynamicrenderingmultisampling/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME dynamicrenderingmultisampling) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/dynamicrenderingmultisampling/build.gradle b/android/examples/dynamicrenderingmultisampling/build.gradle deleted file mode 100644 index de7f4824..00000000 --- a/android/examples/dynamicrenderingmultisampling/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDynamicrenderingmulitsampling" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/dynamicrendering' - into 'assets/shaders/glsl/dynamicrendering' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'voyager.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/dynamicrenderingmultisampling/src/main/AndroidManifest.xml b/android/examples/dynamicrenderingmultisampling/src/main/AndroidManifest.xml deleted file mode 100644 index ccefddb6..00000000 --- a/android/examples/dynamicrenderingmultisampling/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/dynamicrenderingmultisampling/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/dynamicrenderingmultisampling/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/dynamicrenderingmultisampling/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/dynamicstate/CMakeLists.txt b/android/examples/dynamicstate/CMakeLists.txt deleted file mode 100644 index 67dfc8b7..00000000 --- a/android/examples/dynamicstate/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME dynamicstate) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/dynamicstate/build.gradle b/android/examples/dynamicstate/build.gradle deleted file mode 100644 index eef78dc5..00000000 --- a/android/examples/dynamicstate/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDynamicstate" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/pipelines' - into 'assets/shaders/glsl/pipelines' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'treasure_smooth.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/dynamicstate/src/main/AndroidManifest.xml b/android/examples/dynamicstate/src/main/AndroidManifest.xml deleted file mode 100644 index b1798ce7..00000000 --- a/android/examples/dynamicstate/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/dynamicstate/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/dynamicstate/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/dynamicstate/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/dynamicuniformbuffer/CMakeLists.txt b/android/examples/dynamicuniformbuffer/CMakeLists.txt deleted file mode 100644 index 80540406..00000000 --- a/android/examples/dynamicuniformbuffer/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME dynamicuniformbuffer) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/dynamicuniformbuffer/build.gradle b/android/examples/dynamicuniformbuffer/build.gradle deleted file mode 100644 index c743d4bb..00000000 --- a/android/examples/dynamicuniformbuffer/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanDynamicuniformbuffer" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/dynamicuniformbuffer' - into 'assets/shaders/glsl/dynamicuniformbuffer' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/dynamicuniformbuffer/src/main/AndroidManifest.xml b/android/examples/dynamicuniformbuffer/src/main/AndroidManifest.xml deleted file mode 100644 index 171ffc86..00000000 --- a/android/examples/dynamicuniformbuffer/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/dynamicuniformbuffer/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/dynamicuniformbuffer/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/dynamicuniformbuffer/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/gears/CMakeLists.txt b/android/examples/gears/CMakeLists.txt deleted file mode 100644 index c91b527a..00000000 --- a/android/examples/gears/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME gears) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/gears/build.gradle b/android/examples/gears/build.gradle deleted file mode 100644 index 770a11d1..00000000 --- a/android/examples/gears/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanGears" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/gears' - into 'assets/shaders/glsl/gears' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/gears/src/main/AndroidManifest.xml b/android/examples/gears/src/main/AndroidManifest.xml deleted file mode 100644 index da134b43..00000000 --- a/android/examples/gears/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/gears/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/gears/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/gears/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/geometryshader/CMakeLists.txt b/android/examples/geometryshader/CMakeLists.txt deleted file mode 100644 index a743e06a..00000000 --- a/android/examples/geometryshader/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME geometryshader) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/geometryshader/build.gradle b/android/examples/geometryshader/build.gradle deleted file mode 100644 index bddb5ab8..00000000 --- a/android/examples/geometryshader/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanGeometryshader" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/geometryshader' - into 'assets/shaders/glsl/geometryshader' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'suzanne.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/geometryshader/src/main/AndroidManifest.xml b/android/examples/geometryshader/src/main/AndroidManifest.xml deleted file mode 100644 index dfbfd2ca..00000000 --- a/android/examples/geometryshader/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/geometryshader/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/geometryshader/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/geometryshader/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/gltfloading/CMakeLists.txt b/android/examples/gltfloading/CMakeLists.txt deleted file mode 100644 index 47229876..00000000 --- a/android/examples/gltfloading/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME gltfloading) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/gltfloading/build.gradle b/android/examples/gltfloading/build.gradle deleted file mode 100644 index d8327e82..00000000 --- a/android/examples/gltfloading/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanglTFScene" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/gltfloading' - into 'assets/shaders/glsl/gltfloading' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models/FlightHelmet/glTF' - into 'assets/models/FlightHelmet/glTF' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/gltfloading/src/main/AndroidManifest.xml b/android/examples/gltfloading/src/main/AndroidManifest.xml deleted file mode 100644 index 090e46c7..00000000 --- a/android/examples/gltfloading/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/gltfloading/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/gltfloading/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/gltfloading/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/gltfscenerendering/CMakeLists.txt b/android/examples/gltfscenerendering/CMakeLists.txt deleted file mode 100644 index e73fa443..00000000 --- a/android/examples/gltfscenerendering/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME gltfscenerendering) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/gltfscenerendering/build.gradle b/android/examples/gltfscenerendering/build.gradle deleted file mode 100644 index 34660ebc..00000000 --- a/android/examples/gltfscenerendering/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanScenerendering" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath +'glsl/gltfscenerendering' - into 'assets/shaders/glsl/gltfscenerendering' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models/sponza' - into 'assets/models/sponza' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/gltfscenerendering/src/main/AndroidManifest.xml b/android/examples/gltfscenerendering/src/main/AndroidManifest.xml deleted file mode 100644 index 6ce148be..00000000 --- a/android/examples/gltfscenerendering/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/gltfscenerendering/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/gltfscenerendering/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/gltfscenerendering/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/gltfskinning/CMakeLists.txt b/android/examples/gltfskinning/CMakeLists.txt deleted file mode 100644 index 32e4f6b1..00000000 --- a/android/examples/gltfskinning/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME gltfskinning) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/gltfskinning/build.gradle b/android/examples/gltfskinning/build.gradle deleted file mode 100644 index 001d53b6..00000000 --- a/android/examples/gltfskinning/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanglTFSkinning" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into "assets/shaders/glsl/base" - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/gltfskinning' - into 'assets/shaders/glsl/gltfskinning' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models/CesiumMan/glTF' - into 'assets/models/CesiumMan/glTF' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/gltfskinning/src/main/AndroidManifest.xml b/android/examples/gltfskinning/src/main/AndroidManifest.xml deleted file mode 100644 index a9d112f1..00000000 --- a/android/examples/gltfskinning/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/gltfskinning/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/gltfskinning/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/gltfskinning/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/gradle/outputfilename.gradle b/android/examples/gradle/outputfilename.gradle deleted file mode 100644 index e71624b3..00000000 --- a/android/examples/gradle/outputfilename.gradle +++ /dev/null @@ -1,7 +0,0 @@ -android { - applicationVariants.all { variant -> - variant.outputs.all { - outputFileName = "../../../../../bin/" + outputFileName - } - } -} \ No newline at end of file diff --git a/android/examples/graphicspipelinelibrary/CMakeLists.txt b/android/examples/graphicspipelinelibrary/CMakeLists.txt deleted file mode 100644 index d789ea68..00000000 --- a/android/examples/graphicspipelinelibrary/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME graphicspipelinelibrary) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/graphicspipelinelibrary/build.gradle b/android/examples/graphicspipelinelibrary/build.gradle deleted file mode 100644 index 71c17e81..00000000 --- a/android/examples/graphicspipelinelibrary/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanGraphicspipelinelibrary" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/graphicspipelinelibrary' - into 'assets/shaders/glsl/graphicspipelinelibrary' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'color_teapot_spheres.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/graphicspipelinelibrary/src/main/AndroidManifest.xml b/android/examples/graphicspipelinelibrary/src/main/AndroidManifest.xml deleted file mode 100644 index 3a2b38ab..00000000 --- a/android/examples/graphicspipelinelibrary/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/graphicspipelinelibrary/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/graphicspipelinelibrary/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/graphicspipelinelibrary/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/hdr/CMakeLists.txt b/android/examples/hdr/CMakeLists.txt deleted file mode 100644 index 6e84bcef..00000000 --- a/android/examples/hdr/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME hdr) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/hdr/build.gradle b/android/examples/hdr/build.gradle deleted file mode 100644 index 76404a06..00000000 --- a/android/examples/hdr/build.gradle +++ /dev/null @@ -1,96 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanHDR" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/hdr' - into 'assets/shaders/glsl/hdr' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'teapot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'torusknot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'venus.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures/hdr' - into 'assets/textures/hdr' - include 'uffizi_cube.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/hdr/src/main/AndroidManifest.xml b/android/examples/hdr/src/main/AndroidManifest.xml deleted file mode 100644 index f2604321..00000000 --- a/android/examples/hdr/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/hdr/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/hdr/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/hdr/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/hostimagecopy/CMakeLists.txt b/android/examples/hostimagecopy/CMakeLists.txt deleted file mode 100644 index cdee596e..00000000 --- a/android/examples/hostimagecopy/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME hostimagecopy) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/hostimagecopy/build.gradle b/android/examples/hostimagecopy/build.gradle deleted file mode 100644 index e59aba39..00000000 --- a/android/examples/hostimagecopy/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanHostImageCopy" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/texture' - into 'assets/shaders/glsl/texture' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'metalplate01_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'plane_z.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/hostimagecopy/src/main/AndroidManifest.xml b/android/examples/hostimagecopy/src/main/AndroidManifest.xml deleted file mode 100644 index fcd8d7c5..00000000 --- a/android/examples/hostimagecopy/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/hostimagecopy/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/hostimagecopy/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/hostimagecopy/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/imgui/CMakeLists.txt b/android/examples/imgui/CMakeLists.txt deleted file mode 100644 index 6ee5d400..00000000 --- a/android/examples/imgui/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME imgui) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") -file(GLOB ADD_SOURCE "${EXTERNAL_DIR}/imgui/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC} ${ADD_SOURCE}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/imgui/build.gradle b/android/examples/imgui/build.gradle deleted file mode 100644 index 8e46075f..00000000 --- a/android/examples/imgui/build.gradle +++ /dev/null @@ -1,78 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanImGui" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/imgui' - into 'assets/shaders/glsl/imgui' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'vulkanscenemodels.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'vulkanscenebackground.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'vulkanscenelogos.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/imgui/src/main/AndroidManifest.xml b/android/examples/imgui/src/main/AndroidManifest.xml deleted file mode 100644 index 1b4f2ed1..00000000 --- a/android/examples/imgui/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/imgui/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/imgui/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/imgui/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/indirectdraw/CMakeLists.txt b/android/examples/indirectdraw/CMakeLists.txt deleted file mode 100644 index 5480399b..00000000 --- a/android/examples/indirectdraw/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME indirectdraw) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/indirectdraw/build.gradle b/android/examples/indirectdraw/build.gradle deleted file mode 100644 index e21c98dd..00000000 --- a/android/examples/indirectdraw/build.gradle +++ /dev/null @@ -1,90 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanIndirectdraw" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/indirectdraw' - into 'assets/shaders/glsl/indirectdraw' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'plants.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'plane_circle.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'texturearray_plants_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'ground_dry_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/indirectdraw/src/main/AndroidManifest.xml b/android/examples/indirectdraw/src/main/AndroidManifest.xml deleted file mode 100644 index 60fa8e14..00000000 --- a/android/examples/indirectdraw/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/indirectdraw/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/indirectdraw/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/indirectdraw/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/inlineuniformblocks/CMakeLists.txt b/android/examples/inlineuniformblocks/CMakeLists.txt deleted file mode 100644 index 276636c6..00000000 --- a/android/examples/inlineuniformblocks/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME inlineuniformblocks) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/inlineuniformblocks/build.gradle b/android/examples/inlineuniformblocks/build.gradle deleted file mode 100644 index 0892b747..00000000 --- a/android/examples/inlineuniformblocks/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanInlineuniformblocks" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/inlineuniformblocks' - into 'assets/shaders/glsl/inlineuniformblocks' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/inlineuniformblocks/src/main/AndroidManifest.xml b/android/examples/inlineuniformblocks/src/main/AndroidManifest.xml deleted file mode 100644 index e9745391..00000000 --- a/android/examples/inlineuniformblocks/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/inlineuniformblocks/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/inlineuniformblocks/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/inlineuniformblocks/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/inputattachments/CMakeLists.txt b/android/examples/inputattachments/CMakeLists.txt deleted file mode 100644 index d07704e2..00000000 --- a/android/examples/inputattachments/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME inputattachments) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/inputattachments/build.gradle b/android/examples/inputattachments/build.gradle deleted file mode 100644 index 9dace85d..00000000 --- a/android/examples/inputattachments/build.gradle +++ /dev/null @@ -1,70 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanInputattachments" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - main { - jniLibs { - srcDir "${android.ndkDirectory}/sources/third_party/vulkan/src/build-android/jniLibs" - } - } - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/inputattachments' - into 'assets/shaders/glsl/inputattachments' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'treasure_smooth.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/inputattachments/src/main/AndroidManifest.xml b/android/examples/inputattachments/src/main/AndroidManifest.xml deleted file mode 100644 index 0cfc68ca..00000000 --- a/android/examples/inputattachments/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/inputattachments/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/inputattachments/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/inputattachments/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/instancing/CMakeLists.txt b/android/examples/instancing/CMakeLists.txt deleted file mode 100644 index 0949f09c..00000000 --- a/android/examples/instancing/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME instancing) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/instancing/build.gradle b/android/examples/instancing/build.gradle deleted file mode 100644 index 597f79c0..00000000 --- a/android/examples/instancing/build.gradle +++ /dev/null @@ -1,84 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanInstancing" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/instancing' - into 'assets/shaders/glsl/instancing' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'rock01.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'lavaplanet.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'texturearray_rocks*.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'lavaplanet*.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/instancing/src/main/AndroidManifest.xml b/android/examples/instancing/src/main/AndroidManifest.xml deleted file mode 100644 index 6a134704..00000000 --- a/android/examples/instancing/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/instancing/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/instancing/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/instancing/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/meshshader/CMakeLists.txt b/android/examples/meshshader/CMakeLists.txt deleted file mode 100644 index f6f0f28d..00000000 --- a/android/examples/meshshader/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME meshshader) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/meshshader/build.gradle b/android/examples/meshshader/build.gradle deleted file mode 100644 index 81e112cd..00000000 --- a/android/examples/meshshader/build.gradle +++ /dev/null @@ -1,59 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanMeshshader" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/meshshader' - into 'assets/shaders/glsl/meshshader' - include '*.*' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/meshshader/src/main/AndroidManifest.xml b/android/examples/meshshader/src/main/AndroidManifest.xml deleted file mode 100644 index 89ad0f7a..00000000 --- a/android/examples/meshshader/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/meshshader/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/meshshader/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/meshshader/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/multisampling/CMakeLists.txt b/android/examples/multisampling/CMakeLists.txt deleted file mode 100644 index 7dd374c7..00000000 --- a/android/examples/multisampling/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME multisampling) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/multisampling/build.gradle b/android/examples/multisampling/build.gradle deleted file mode 100644 index c0c620bb..00000000 --- a/android/examples/multisampling/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanMultisampling" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/multisampling' - into 'assets/shaders/glsl/multisampling' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'voyager.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/multisampling/src/main/AndroidManifest.xml b/android/examples/multisampling/src/main/AndroidManifest.xml deleted file mode 100644 index aa113840..00000000 --- a/android/examples/multisampling/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/multisampling/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/multisampling/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/multisampling/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/multithreading/CMakeLists.txt b/android/examples/multithreading/CMakeLists.txt deleted file mode 100644 index e7e07b83..00000000 --- a/android/examples/multithreading/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME multithreading) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/multithreading/build.gradle b/android/examples/multithreading/build.gradle deleted file mode 100644 index fbd26b6c..00000000 --- a/android/examples/multithreading/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanMultithreading" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/multithreading' - into 'assets/shaders/glsl/multithreading' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'retroufo_red_lowpoly.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/multithreading/src/main/AndroidManifest.xml b/android/examples/multithreading/src/main/AndroidManifest.xml deleted file mode 100644 index f002469a..00000000 --- a/android/examples/multithreading/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/multithreading/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/multithreading/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/multithreading/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/multiview/CMakeLists.txt b/android/examples/multiview/CMakeLists.txt deleted file mode 100644 index 5280226c..00000000 --- a/android/examples/multiview/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME multiview) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/multiview/build.gradle b/android/examples/multiview/build.gradle deleted file mode 100644 index d2acf842..00000000 --- a/android/examples/multiview/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanMultiview" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/multiview' - into 'assets/shaders/glsl/multiview' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sampleroom.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/multiview/src/main/AndroidManifest.xml b/android/examples/multiview/src/main/AndroidManifest.xml deleted file mode 100644 index 274906e2..00000000 --- a/android/examples/multiview/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/multiview/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/multiview/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/multiview/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/negativeviewportheight/CMakeLists.txt b/android/examples/negativeviewportheight/CMakeLists.txt deleted file mode 100644 index 9554a347..00000000 --- a/android/examples/negativeviewportheight/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME negativeviewportheight) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/negativeviewportheight/build.gradle b/android/examples/negativeviewportheight/build.gradle deleted file mode 100644 index 85b9642c..00000000 --- a/android/examples/negativeviewportheight/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanNegativeviewportheight" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/negativeviewportheight' - into 'assets/shaders/glsl/negativeviewportheight' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'texture_orientation_ccw_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'texture_orientation_cw_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/negativeviewportheight/src/main/AndroidManifest.xml b/android/examples/negativeviewportheight/src/main/AndroidManifest.xml deleted file mode 100644 index 3455af63..00000000 --- a/android/examples/negativeviewportheight/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/negativeviewportheight/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/negativeviewportheight/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/negativeviewportheight/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/occlusionquery/CMakeLists.txt b/android/examples/occlusionquery/CMakeLists.txt deleted file mode 100644 index b33dbdcb..00000000 --- a/android/examples/occlusionquery/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME occlusionquery) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/occlusionquery/build.gradle b/android/examples/occlusionquery/build.gradle deleted file mode 100644 index 9eaa7e0c..00000000 --- a/android/examples/occlusionquery/build.gradle +++ /dev/null @@ -1,78 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanOcclusionquery" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/occlusionquery' - into 'assets/shaders/glsl/occlusionquery' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'plane_z.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'teapot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/occlusionquery/src/main/AndroidManifest.xml b/android/examples/occlusionquery/src/main/AndroidManifest.xml deleted file mode 100644 index ab7386b9..00000000 --- a/android/examples/occlusionquery/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/occlusionquery/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/occlusionquery/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/occlusionquery/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/offscreen/CMakeLists.txt b/android/examples/offscreen/CMakeLists.txt deleted file mode 100644 index 35f62af4..00000000 --- a/android/examples/offscreen/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME offscreen) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/offscreen/build.gradle b/android/examples/offscreen/build.gradle deleted file mode 100644 index 9b700c7c..00000000 --- a/android/examples/offscreen/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanOffscreen" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/offscreen' - into 'assets/shaders/glsl/offscreen' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'plane.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'chinesedragon.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/offscreen/src/main/AndroidManifest.xml b/android/examples/offscreen/src/main/AndroidManifest.xml deleted file mode 100644 index 97f3ce24..00000000 --- a/android/examples/offscreen/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/offscreen/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/offscreen/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/offscreen/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/oit/CMakeLists.txt b/android/examples/oit/CMakeLists.txt deleted file mode 100644 index 86202e17..00000000 --- a/android/examples/oit/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME oit) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/oit/build.gradle b/android/examples/oit/build.gradle deleted file mode 100644 index 28922c1d..00000000 --- a/android/examples/oit/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanOrderIndependentTransparency" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/oit' - into 'assets/shaders/glsl/oit' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/oit/src/main/AndroidManifest.xml b/android/examples/oit/src/main/AndroidManifest.xml deleted file mode 100644 index 994c2877..00000000 --- a/android/examples/oit/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/oit/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/oit/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/oit/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/parallaxmapping/CMakeLists.txt b/android/examples/parallaxmapping/CMakeLists.txt deleted file mode 100644 index a3204944..00000000 --- a/android/examples/parallaxmapping/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME parallaxmapping) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/parallaxmapping/build.gradle b/android/examples/parallaxmapping/build.gradle deleted file mode 100644 index 68100a2a..00000000 --- a/android/examples/parallaxmapping/build.gradle +++ /dev/null @@ -1,78 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanParallaxmapping" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/parallaxmapping' - into 'assets/shaders/glsl/parallaxmapping' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'plane.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'rocks_normal_height_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'rocks_color*.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/parallaxmapping/src/main/AndroidManifest.xml b/android/examples/parallaxmapping/src/main/AndroidManifest.xml deleted file mode 100644 index a2b56a7a..00000000 --- a/android/examples/parallaxmapping/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/parallaxmapping/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/parallaxmapping/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/parallaxmapping/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/particlesystem/CMakeLists.txt b/android/examples/particlesystem/CMakeLists.txt deleted file mode 100644 index 99a3861e..00000000 --- a/android/examples/particlesystem/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME particlesystem) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/particlesystem/build.gradle b/android/examples/particlesystem/build.gradle deleted file mode 100644 index 054da9c9..00000000 --- a/android/examples/particlesystem/build.gradle +++ /dev/null @@ -1,90 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanParticlesystem" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/particlesystem' - into 'assets/shaders/glsl/particlesystem' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'fireplace.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'particle_fire.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'particle_smoke.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'fireplace_normalmap*.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'fireplace_colormap*.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/particlesystem/src/main/AndroidManifest.xml b/android/examples/particlesystem/src/main/AndroidManifest.xml deleted file mode 100644 index 51a08ade..00000000 --- a/android/examples/particlesystem/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/particlesystem/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/particlesystem/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/particlesystem/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/pbrbasic/CMakeLists.txt b/android/examples/pbrbasic/CMakeLists.txt deleted file mode 100644 index fccf7131..00000000 --- a/android/examples/pbrbasic/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME pbrbasic) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/pbrbasic/build.gradle b/android/examples/pbrbasic/build.gradle deleted file mode 100644 index 1dd8a954..00000000 --- a/android/examples/pbrbasic/build.gradle +++ /dev/null @@ -1,84 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanPBRBasic" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/pbrbasic' - into 'assets/shaders/glsl/pbrbasic' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'teapot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'torusknot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'venus.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/pbrbasic/src/main/AndroidManifest.xml b/android/examples/pbrbasic/src/main/AndroidManifest.xml deleted file mode 100644 index 38e5241a..00000000 --- a/android/examples/pbrbasic/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/pbrbasic/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/pbrbasic/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/pbrbasic/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/pbribl/CMakeLists.txt b/android/examples/pbribl/CMakeLists.txt deleted file mode 100644 index daaf7c9c..00000000 --- a/android/examples/pbribl/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME pbribl) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/pbribl/build.gradle b/android/examples/pbribl/build.gradle deleted file mode 100644 index a2661f5f..00000000 --- a/android/examples/pbribl/build.gradle +++ /dev/null @@ -1,96 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanPBRIBL" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/pbribl' - into 'assets/shaders/glsl/pbribl' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'teapot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'torusknot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'venus.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures/hdr' - into 'assets/textures/hdr' - include 'pisa_cube.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/pbribl/src/main/AndroidManifest.xml b/android/examples/pbribl/src/main/AndroidManifest.xml deleted file mode 100644 index af6d2595..00000000 --- a/android/examples/pbribl/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/pbribl/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/pbribl/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/pbribl/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/pbrtexture/CMakeLists.txt b/android/examples/pbrtexture/CMakeLists.txt deleted file mode 100644 index 1f08cd14..00000000 --- a/android/examples/pbrtexture/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME pbrtexture) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/pbrtexture/build.gradle b/android/examples/pbrtexture/build.gradle deleted file mode 100644 index d1ca4b6f..00000000 --- a/android/examples/pbrtexture/build.gradle +++ /dev/null @@ -1,78 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanPBRTexture" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/pbrtexture' - into 'assets/shaders/glsl/pbrtexture' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures/hdr' - into 'assets/textures/hdr' - include 'gcanyon_cube.ktx' - } - - copy { - from rootProject.ext.assetPath + 'models/cerberus' - into 'assets/models/cerberus' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/pbrtexture/src/main/AndroidManifest.xml b/android/examples/pbrtexture/src/main/AndroidManifest.xml deleted file mode 100644 index 2f048ce4..00000000 --- a/android/examples/pbrtexture/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/pbrtexture/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/pbrtexture/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/pbrtexture/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/pipelines/CMakeLists.txt b/android/examples/pipelines/CMakeLists.txt deleted file mode 100644 index b9e2e61d..00000000 --- a/android/examples/pipelines/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME pipelines) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/gli) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/pipelines/build.gradle b/android/examples/pipelines/build.gradle deleted file mode 100644 index 5ea5befa..00000000 --- a/android/examples/pipelines/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanPipelines" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/pipelines' - into 'assets/shaders/glsl/pipelines' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'treasure_smooth.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/pipelines/src/main/AndroidManifest.xml b/android/examples/pipelines/src/main/AndroidManifest.xml deleted file mode 100644 index 6fb6beed..00000000 --- a/android/examples/pipelines/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/pipelines/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/pipelines/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/pipelines/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/pipelinestatistics/CMakeLists.txt b/android/examples/pipelinestatistics/CMakeLists.txt deleted file mode 100644 index c2bbec2b..00000000 --- a/android/examples/pipelinestatistics/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME pipelinestatistics) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/gli) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/pipelinestatistics/build.gradle b/android/examples/pipelinestatistics/build.gradle deleted file mode 100644 index 37a65c3e..00000000 --- a/android/examples/pipelinestatistics/build.gradle +++ /dev/null @@ -1,84 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanPipelinestatistics" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/pipelinestatistics' - into 'assets/shaders/glsl/pipelinestatistics' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'teapot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'torusknot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'venus.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/pipelinestatistics/src/main/AndroidManifest.xml b/android/examples/pipelinestatistics/src/main/AndroidManifest.xml deleted file mode 100644 index 383bdc9a..00000000 --- a/android/examples/pipelinestatistics/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/pipelinestatistics/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/pipelinestatistics/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/pipelinestatistics/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/pushconstants/CMakeLists.txt b/android/examples/pushconstants/CMakeLists.txt deleted file mode 100644 index 349ad3c1..00000000 --- a/android/examples/pushconstants/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME pushconstants) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/pushconstants/build.gradle b/android/examples/pushconstants/build.gradle deleted file mode 100644 index 7bc6f50e..00000000 --- a/android/examples/pushconstants/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanPushconstants" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/pushconstants' - into 'assets/shaders/glsl/pushconstants' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'samplescene.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/pushconstants/src/main/AndroidManifest.xml b/android/examples/pushconstants/src/main/AndroidManifest.xml deleted file mode 100644 index ae50caea..00000000 --- a/android/examples/pushconstants/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/pushconstants/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/pushconstants/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/pushconstants/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/pushdescriptors/CMakeLists.txt b/android/examples/pushdescriptors/CMakeLists.txt deleted file mode 100644 index cecf5905..00000000 --- a/android/examples/pushdescriptors/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME pushdescriptors) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/pushdescriptors/build.gradle b/android/examples/pushdescriptors/build.gradle deleted file mode 100644 index 87155a70..00000000 --- a/android/examples/pushdescriptors/build.gradle +++ /dev/null @@ -1,78 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanPushdescriptors" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/pushdescriptors' - into 'assets/shaders/glsl/pushdescriptors' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'crate01_color_height_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'crate02_color_height_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/pushdescriptors/src/main/AndroidManifest.xml b/android/examples/pushdescriptors/src/main/AndroidManifest.xml deleted file mode 100644 index f16f8336..00000000 --- a/android/examples/pushdescriptors/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/pushdescriptors/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/pushdescriptors/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/pushdescriptors/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/radialblur/CMakeLists.txt b/android/examples/radialblur/CMakeLists.txt deleted file mode 100644 index b684bad9..00000000 --- a/android/examples/radialblur/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME radialblur) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/radialblur/build.gradle b/android/examples/radialblur/build.gradle deleted file mode 100644 index fcfbe6d1..00000000 --- a/android/examples/radialblur/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRadialblur" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/radialblur' - into 'assets/shaders/glsl/radialblur' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'glowsphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'particle_gradient_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/radialblur/src/main/AndroidManifest.xml b/android/examples/radialblur/src/main/AndroidManifest.xml deleted file mode 100644 index fc5cbf05..00000000 --- a/android/examples/radialblur/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/radialblur/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/radialblur/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/radialblur/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/rayquery/CMakeLists.txt b/android/examples/rayquery/CMakeLists.txt deleted file mode 100644 index 4d29127a..00000000 --- a/android/examples/rayquery/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME rayquery) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/rayquery/build.gradle b/android/examples/rayquery/build.gradle deleted file mode 100644 index 75b084ca..00000000 --- a/android/examples/rayquery/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRayQuery" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/rayquery' - into 'assets/shaders/glsl/rayquery' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'vulkanscene_shadow.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/rayquery/src/main/AndroidManifest.xml b/android/examples/rayquery/src/main/AndroidManifest.xml deleted file mode 100644 index c39760fa..00000000 --- a/android/examples/rayquery/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/rayquery/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/rayquery/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/rayquery/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/raytracingbasic/CMakeLists.txt b/android/examples/raytracingbasic/CMakeLists.txt deleted file mode 100644 index 25138d07..00000000 --- a/android/examples/raytracingbasic/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME raytracingbasic) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/raytracingbasic/build.gradle b/android/examples/raytracingbasic/build.gradle deleted file mode 100644 index 3e2cabc9..00000000 --- a/android/examples/raytracingbasic/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRaytracingbasic" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/raytracingbasic' - into 'assets/shaders/glsl/raytracingbasic' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/raytracingbasic/src/main/AndroidManifest.xml b/android/examples/raytracingbasic/src/main/AndroidManifest.xml deleted file mode 100644 index 0336f20c..00000000 --- a/android/examples/raytracingbasic/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/raytracingbasic/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/raytracingbasic/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/raytracingbasic/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/raytracingcallable/CMakeLists.txt b/android/examples/raytracingcallable/CMakeLists.txt deleted file mode 100644 index 02fbd15d..00000000 --- a/android/examples/raytracingcallable/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME raytracingcallable) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/raytracingcallable/build.gradle b/android/examples/raytracingcallable/build.gradle deleted file mode 100644 index ce9a314e..00000000 --- a/android/examples/raytracingcallable/build.gradle +++ /dev/null @@ -1,59 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRaytracingcallable" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/raytracingcallable' - into 'assets/shaders/glsl/raytracingcallable' - include '*.*' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/raytracingcallable/src/main/AndroidManifest.xml b/android/examples/raytracingcallable/src/main/AndroidManifest.xml deleted file mode 100644 index 48486a72..00000000 --- a/android/examples/raytracingcallable/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/raytracingcallable/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/raytracingcallable/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/raytracingcallable/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/raytracinggltf/CMakeLists.txt b/android/examples/raytracinggltf/CMakeLists.txt deleted file mode 100644 index bfe906f1..00000000 --- a/android/examples/raytracinggltf/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME raytracinggltf) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/raytracinggltf/build.gradle b/android/examples/raytracinggltf/build.gradle deleted file mode 100644 index 2f8df33e..00000000 --- a/android/examples/raytracinggltf/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRaytracinggltf" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/raytracinggltf' - into 'assets/shaders/glsl/raytracinggltf' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models/FlightHelmet/glTF' - into 'assets/models/FlightHelmet/glTF' - include '*.*' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/raytracinggltf/src/main/AndroidManifest.xml b/android/examples/raytracinggltf/src/main/AndroidManifest.xml deleted file mode 100644 index 8814f938..00000000 --- a/android/examples/raytracinggltf/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/examples/raytracinggltf/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/raytracinggltf/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/raytracinggltf/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/raytracingintersection/CMakeLists.txt b/android/examples/raytracingintersection/CMakeLists.txt deleted file mode 100644 index 5ae76ede..00000000 --- a/android/examples/raytracingintersection/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME raytracingintersection) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/raytracingintersection/build.gradle b/android/examples/raytracingintersection/build.gradle deleted file mode 100644 index d0219af5..00000000 --- a/android/examples/raytracingintersection/build.gradle +++ /dev/null @@ -1,59 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRaytracingintersection" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/raytracingintersection' - into 'assets/shaders/glsl/raytracingintersection' - include '*.*' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/raytracingintersection/src/main/AndroidManifest.xml b/android/examples/raytracingintersection/src/main/AndroidManifest.xml deleted file mode 100644 index 79217a3d..00000000 --- a/android/examples/raytracingintersection/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/raytracingintersection/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/raytracingintersection/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/raytracingintersection/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/raytracingpositionfetch/CMakeLists.txt b/android/examples/raytracingpositionfetch/CMakeLists.txt deleted file mode 100644 index 04f57764..00000000 --- a/android/examples/raytracingpositionfetch/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME raytracingpositionfetch) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/raytracingpositionfetch/build.gradle b/android/examples/raytracingpositionfetch/build.gradle deleted file mode 100644 index b70bb790..00000000 --- a/android/examples/raytracingpositionfetch/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRaytracingpositionfetch" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/raytracingpositionfetch' - into 'assets/shaders/glsl/raytracingpositionfetch' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'treasure_smooth.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/raytracingpositionfetch/src/main/AndroidManifest.xml b/android/examples/raytracingpositionfetch/src/main/AndroidManifest.xml deleted file mode 100644 index 9083b536..00000000 --- a/android/examples/raytracingpositionfetch/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/raytracingpositionfetch/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/raytracingpositionfetch/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/raytracingpositionfetch/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/raytracingreflections/CMakeLists.txt b/android/examples/raytracingreflections/CMakeLists.txt deleted file mode 100644 index cba5509a..00000000 --- a/android/examples/raytracingreflections/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME raytracingreflections) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/raytracingreflections/build.gradle b/android/examples/raytracingreflections/build.gradle deleted file mode 100644 index 55c50d32..00000000 --- a/android/examples/raytracingreflections/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRaytracingreflections" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/raytracingreflections' - into 'assets/shaders/glsl/raytracingreflections' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'reflection_scene.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/raytracingreflections/src/main/AndroidManifest.xml b/android/examples/raytracingreflections/src/main/AndroidManifest.xml deleted file mode 100644 index 1fe9d2d3..00000000 --- a/android/examples/raytracingreflections/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/raytracingreflections/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/raytracingreflections/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/raytracingreflections/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/raytracingsbtdata/CMakeLists.txt b/android/examples/raytracingsbtdata/CMakeLists.txt deleted file mode 100644 index 103555e5..00000000 --- a/android/examples/raytracingsbtdata/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME raytracingsbtdata) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/raytracingsbtdata/build.gradle b/android/examples/raytracingsbtdata/build.gradle deleted file mode 100644 index b495acd8..00000000 --- a/android/examples/raytracingsbtdata/build.gradle +++ /dev/null @@ -1,59 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRaytracingsbtdata" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/raytracingsbtdata' - into 'assets/shaders/glsl/raytracingsbtdata' - include '*.*' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/raytracingsbtdata/src/main/AndroidManifest.xml b/android/examples/raytracingsbtdata/src/main/AndroidManifest.xml deleted file mode 100644 index 75e7fea6..00000000 --- a/android/examples/raytracingsbtdata/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/raytracingsbtdata/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/raytracingsbtdata/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/raytracingsbtdata/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/raytracingshadows/CMakeLists.txt b/android/examples/raytracingshadows/CMakeLists.txt deleted file mode 100644 index d273e282..00000000 --- a/android/examples/raytracingshadows/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME raytracingshadows) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/raytracingshadows/build.gradle b/android/examples/raytracingshadows/build.gradle deleted file mode 100644 index e951cba9..00000000 --- a/android/examples/raytracingshadows/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRaytracingshadows" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/raytracingshadows' - into 'assets/shaders/glsl/raytracingshadows' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'vulkanscene_shadow.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/raytracingshadows/src/main/AndroidManifest.xml b/android/examples/raytracingshadows/src/main/AndroidManifest.xml deleted file mode 100644 index 9888eec4..00000000 --- a/android/examples/raytracingshadows/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/raytracingshadows/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/raytracingshadows/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/raytracingshadows/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/raytracingtextures/CMakeLists.txt b/android/examples/raytracingtextures/CMakeLists.txt deleted file mode 100644 index cf3fad0c..00000000 --- a/android/examples/raytracingtextures/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME raytracingtextures) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/raytracingtextures/build.gradle b/android/examples/raytracingtextures/build.gradle deleted file mode 100644 index d9abe667..00000000 --- a/android/examples/raytracingtextures/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRaytracingtextures" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/raytracingtextures' - into 'assets/shaders/glsl/raytracingtextures' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'gratefloor_rgba.ktx' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/raytracingtextures/src/main/AndroidManifest.xml b/android/examples/raytracingtextures/src/main/AndroidManifest.xml deleted file mode 100644 index 6d1b12e2..00000000 --- a/android/examples/raytracingtextures/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/raytracingtextures/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/raytracingtextures/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/raytracingtextures/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/renderheadless/CMakeLists.txt b/android/examples/renderheadless/CMakeLists.txt deleted file mode 100644 index 6e7b3bb1..00000000 --- a/android/examples/renderheadless/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME renderheadless) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/renderheadless/build.gradle b/android/examples/renderheadless/build.gradle deleted file mode 100644 index 87bc76e8..00000000 --- a/android/examples/renderheadless/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanRenderheadless" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/renderheadless' - into 'assets/shaders/glsl/renderheadless' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/renderheadless/src/main/AndroidManifest.xml b/android/examples/renderheadless/src/main/AndroidManifest.xml deleted file mode 100644 index 918f513b..00000000 --- a/android/examples/renderheadless/src/main/AndroidManifest.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/android/examples/renderheadless/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/renderheadless/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/renderheadless/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/screenshot/CMakeLists.txt b/android/examples/screenshot/CMakeLists.txt deleted file mode 100644 index 1ef51c7d..00000000 --- a/android/examples/screenshot/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME screenshot) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/screenshot/build.gradle b/android/examples/screenshot/build.gradle deleted file mode 100644 index 196a6aa9..00000000 --- a/android/examples/screenshot/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanScreenshot" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/screenshot' - into 'assets/shaders/glsl/screenshot' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'chinesedragon.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/screenshot/src/main/AndroidManifest.xml b/android/examples/screenshot/src/main/AndroidManifest.xml deleted file mode 100644 index 829bbf20..00000000 --- a/android/examples/screenshot/src/main/AndroidManifest.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/android/examples/screenshot/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/screenshot/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/screenshot/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/shaderobjects/CMakeLists.txt b/android/examples/shaderobjects/CMakeLists.txt deleted file mode 100644 index 90086789..00000000 --- a/android/examples/shaderobjects/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME shaderobjects) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/shaderobjects/build.gradle b/android/examples/shaderobjects/build.gradle deleted file mode 100644 index ce056707..00000000 --- a/android/examples/shaderobjects/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanShaderobjects" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/shaderobjects' - into 'assets/shaders/glsl/shaderobjects' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'treasure_smooth.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/shaderobjects/src/main/AndroidManifest.xml b/android/examples/shaderobjects/src/main/AndroidManifest.xml deleted file mode 100644 index 0f6f6c43..00000000 --- a/android/examples/shaderobjects/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/shaderobjects/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/shaderobjects/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/shaderobjects/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/shadowmapping/CMakeLists.txt b/android/examples/shadowmapping/CMakeLists.txt deleted file mode 100644 index 2400cff9..00000000 --- a/android/examples/shadowmapping/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME shadowmapping) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/shadowmapping/build.gradle b/android/examples/shadowmapping/build.gradle deleted file mode 100644 index e25b24a8..00000000 --- a/android/examples/shadowmapping/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanShadowmapping" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/shadowmapping' - into 'assets/shaders/glsl/shadowmapping' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'vulkanscene_shadow.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'samplescene.gltf' - } - -} - -preBuild.dependsOn copyTask diff --git a/android/examples/shadowmapping/src/main/AndroidManifest.xml b/android/examples/shadowmapping/src/main/AndroidManifest.xml deleted file mode 100644 index 859e5afc..00000000 --- a/android/examples/shadowmapping/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/shadowmapping/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/shadowmapping/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/shadowmapping/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/shadowmappingcascade/CMakeLists.txt b/android/examples/shadowmappingcascade/CMakeLists.txt deleted file mode 100644 index d5ce298f..00000000 --- a/android/examples/shadowmappingcascade/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME shadowmappingcascade) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/shadowmappingcascade/build.gradle b/android/examples/shadowmappingcascade/build.gradle deleted file mode 100644 index ce5064d5..00000000 --- a/android/examples/shadowmappingcascade/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanShadowmappingcascade" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/shadowmappingcascade' - into 'assets/shaders/glsl/shadowmappingcascade' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'terrain_gridlines.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'oaktree.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/shadowmappingcascade/src/main/AndroidManifest.xml b/android/examples/shadowmappingcascade/src/main/AndroidManifest.xml deleted file mode 100644 index 9eb23c03..00000000 --- a/android/examples/shadowmappingcascade/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/shadowmappingcascade/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/shadowmappingcascade/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/shadowmappingcascade/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/shadowmappingomni/CMakeLists.txt b/android/examples/shadowmappingomni/CMakeLists.txt deleted file mode 100644 index 06ff0248..00000000 --- a/android/examples/shadowmappingomni/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME shadowmappingomni) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/shadowmappingomni/build.gradle b/android/examples/shadowmappingomni/build.gradle deleted file mode 100644 index 019a4341..00000000 --- a/android/examples/shadowmappingomni/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanShadowmappingomni" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/shadowmappingomni' - into 'assets/shaders/glsl/shadowmappingomni' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'shadowscene_fire.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/shadowmappingomni/src/main/AndroidManifest.xml b/android/examples/shadowmappingomni/src/main/AndroidManifest.xml deleted file mode 100644 index 0fe3262a..00000000 --- a/android/examples/shadowmappingomni/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/shadowmappingomni/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/shadowmappingomni/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/shadowmappingomni/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/specializationconstants/CMakeLists.txt b/android/examples/specializationconstants/CMakeLists.txt deleted file mode 100644 index 179842ab..00000000 --- a/android/examples/specializationconstants/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME specializationconstants) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/specializationconstants/build.gradle b/android/examples/specializationconstants/build.gradle deleted file mode 100644 index c48bbd84..00000000 --- a/android/examples/specializationconstants/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanSpecializationconstants" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/specializationconstants' - into 'assets/shaders/glsl/specializationconstants' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'color_teapot_spheres.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'metalplate_nomips_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/specializationconstants/src/main/AndroidManifest.xml b/android/examples/specializationconstants/src/main/AndroidManifest.xml deleted file mode 100644 index aa6e33c0..00000000 --- a/android/examples/specializationconstants/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/specializationconstants/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/specializationconstants/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/specializationconstants/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/sphericalenvmapping/CMakeLists.txt b/android/examples/sphericalenvmapping/CMakeLists.txt deleted file mode 100644 index 810d62e6..00000000 --- a/android/examples/sphericalenvmapping/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME sphericalenvmapping) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/sphericalenvmapping/build.gradle b/android/examples/sphericalenvmapping/build.gradle deleted file mode 100644 index e542ccd4..00000000 --- a/android/examples/sphericalenvmapping/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanSphericalenvmapping" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/sphericalenvmapping' - into 'assets/shaders/glsl/sphericalenvmapping' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'chinesedragon.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'matcap_array_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/sphericalenvmapping/src/main/AndroidManifest.xml b/android/examples/sphericalenvmapping/src/main/AndroidManifest.xml deleted file mode 100644 index 17a4f280..00000000 --- a/android/examples/sphericalenvmapping/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/sphericalenvmapping/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/sphericalenvmapping/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/sphericalenvmapping/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/ssao/CMakeLists.txt b/android/examples/ssao/CMakeLists.txt deleted file mode 100644 index 7a4355d5..00000000 --- a/android/examples/ssao/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME ssao) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/ssao/build.gradle b/android/examples/ssao/build.gradle deleted file mode 100644 index d9f76090..00000000 --- a/android/examples/ssao/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanSSAO" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/ssao' - into 'assets/shaders/glsl/ssao' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models/sponza' - into 'assets/models/sponza' - include '*.*' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/ssao/src/main/AndroidManifest.xml b/android/examples/ssao/src/main/AndroidManifest.xml deleted file mode 100644 index dad1de75..00000000 --- a/android/examples/ssao/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/ssao/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/ssao/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/ssao/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/stencilbuffer/CMakeLists.txt b/android/examples/stencilbuffer/CMakeLists.txt deleted file mode 100644 index 5f75f0f7..00000000 --- a/android/examples/stencilbuffer/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME stencilbuffer) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/stencilbuffer/build.gradle b/android/examples/stencilbuffer/build.gradle deleted file mode 100644 index 10f97582..00000000 --- a/android/examples/stencilbuffer/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanStencilbuffer" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/stencilbuffer' - into 'assets/shaders/glsl/stencilbuffer' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'venus.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/stencilbuffer/src/main/AndroidManifest.xml b/android/examples/stencilbuffer/src/main/AndroidManifest.xml deleted file mode 100644 index 8b020316..00000000 --- a/android/examples/stencilbuffer/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/stencilbuffer/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/stencilbuffer/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/stencilbuffer/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/subpasses/CMakeLists.txt b/android/examples/subpasses/CMakeLists.txt deleted file mode 100644 index 707fbbc4..00000000 --- a/android/examples/subpasses/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME subpasses) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/subpasses/build.gradle b/android/examples/subpasses/build.gradle deleted file mode 100644 index 9e83166d..00000000 --- a/android/examples/subpasses/build.gradle +++ /dev/null @@ -1,78 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanSubpasses" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/subpasses' - into 'assets/shaders/glsl/subpasses' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'samplebuilding.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'samplebuilding_glass.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'colored_glass_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/subpasses/src/main/AndroidManifest.xml b/android/examples/subpasses/src/main/AndroidManifest.xml deleted file mode 100644 index 3a7a1325..00000000 --- a/android/examples/subpasses/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/subpasses/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/subpasses/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/subpasses/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/terraintessellation/CMakeLists.txt b/android/examples/terraintessellation/CMakeLists.txt deleted file mode 100644 index ad3a0bf6..00000000 --- a/android/examples/terraintessellation/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME terraintessellation) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/terraintessellation/build.gradle b/android/examples/terraintessellation/build.gradle deleted file mode 100644 index 4400df2d..00000000 --- a/android/examples/terraintessellation/build.gradle +++ /dev/null @@ -1,84 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTerraintessellation" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/terraintessellation' - into 'assets/shaders/glsl/terraintessellation' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'skysphere*.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'terrain_texturearray*.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'terrain_heightmap_r16.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/terraintessellation/src/main/AndroidManifest.xml b/android/examples/terraintessellation/src/main/AndroidManifest.xml deleted file mode 100644 index f40a43ca..00000000 --- a/android/examples/terraintessellation/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/terraintessellation/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/terraintessellation/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/terraintessellation/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/tessellation/CMakeLists.txt b/android/examples/tessellation/CMakeLists.txt deleted file mode 100644 index 0de786e5..00000000 --- a/android/examples/tessellation/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME tessellation) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/tessellation/build.gradle b/android/examples/tessellation/build.gradle deleted file mode 100644 index e60902a1..00000000 --- a/android/examples/tessellation/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTessellation" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/tessellation' - into 'assets/shaders/glsl/tessellation' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'deer.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/tessellation/src/main/AndroidManifest.xml b/android/examples/tessellation/src/main/AndroidManifest.xml deleted file mode 100644 index d9733f1d..00000000 --- a/android/examples/tessellation/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/tessellation/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/tessellation/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/tessellation/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/textoverlay/CMakeLists.txt b/android/examples/textoverlay/CMakeLists.txt deleted file mode 100644 index 8f8f962a..00000000 --- a/android/examples/textoverlay/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME textoverlay) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/gli) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/textoverlay/build.gradle b/android/examples/textoverlay/build.gradle deleted file mode 100644 index 617bcc81..00000000 --- a/android/examples/textoverlay/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTextoverlay" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/textoverlay' - into 'assets/shaders/glsl/textoverlay' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/textoverlay/src/main/AndroidManifest.xml b/android/examples/textoverlay/src/main/AndroidManifest.xml deleted file mode 100644 index 0d0144e3..00000000 --- a/android/examples/textoverlay/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/textoverlay/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/textoverlay/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/textoverlay/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/texture/CMakeLists.txt b/android/examples/texture/CMakeLists.txt deleted file mode 100644 index a743d972..00000000 --- a/android/examples/texture/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME texture) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/texture/build.gradle b/android/examples/texture/build.gradle deleted file mode 100644 index 61f08645..00000000 --- a/android/examples/texture/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTexture" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/texture' - into 'assets/shaders/glsl/texture' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'metalplate01_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/texture/src/main/AndroidManifest.xml b/android/examples/texture/src/main/AndroidManifest.xml deleted file mode 100644 index fc670531..00000000 --- a/android/examples/texture/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/texture/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/texture/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/texture/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/texture3d/CMakeLists.txt b/android/examples/texture3d/CMakeLists.txt deleted file mode 100644 index 86a9a06f..00000000 --- a/android/examples/texture3d/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME texture3d) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/texture3d/build.gradle b/android/examples/texture3d/build.gradle deleted file mode 100644 index 9805bfa5..00000000 --- a/android/examples/texture3d/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTexture3d" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/texture3d' - into 'assets/shaders/glsl/texture3d' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/texture3d/src/main/AndroidManifest.xml b/android/examples/texture3d/src/main/AndroidManifest.xml deleted file mode 100644 index 0d74927b..00000000 --- a/android/examples/texture3d/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/texture3d/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/texture3d/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/texture3d/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/texturearray/CMakeLists.txt b/android/examples/texturearray/CMakeLists.txt deleted file mode 100644 index f1932575..00000000 --- a/android/examples/texturearray/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME texturearray) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/texturearray/build.gradle b/android/examples/texturearray/build.gradle deleted file mode 100644 index 90b528b2..00000000 --- a/android/examples/texturearray/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTexturearray" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/texturearray' - into 'assets/shaders/glsl/texturearray' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'texturearray_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/texturearray/src/main/AndroidManifest.xml b/android/examples/texturearray/src/main/AndroidManifest.xml deleted file mode 100644 index c1a04330..00000000 --- a/android/examples/texturearray/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/texturearray/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/texturearray/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/texturearray/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/texturecubemap/CMakeLists.txt b/android/examples/texturecubemap/CMakeLists.txt deleted file mode 100644 index 02f574e3..00000000 --- a/android/examples/texturecubemap/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME texturecubemap) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/texturecubemap/build.gradle b/android/examples/texturecubemap/build.gradle deleted file mode 100644 index dbcfc8a9..00000000 --- a/android/examples/texturecubemap/build.gradle +++ /dev/null @@ -1,96 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTexturecubemap" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/texturecubemap' - into 'assets/shaders/glsl/texturecubemap' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'teapot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'torusknot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'venus.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'cubemap_yokohama_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/texturecubemap/src/main/AndroidManifest.xml b/android/examples/texturecubemap/src/main/AndroidManifest.xml deleted file mode 100644 index e2914845..00000000 --- a/android/examples/texturecubemap/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/texturecubemap/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/texturecubemap/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/texturecubemap/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/texturecubemaparray/CMakeLists.txt b/android/examples/texturecubemaparray/CMakeLists.txt deleted file mode 100644 index 24ca68e0..00000000 --- a/android/examples/texturecubemaparray/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME texturecubemaparray) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/texturecubemaparray/build.gradle b/android/examples/texturecubemaparray/build.gradle deleted file mode 100644 index a9f68f4d..00000000 --- a/android/examples/texturecubemaparray/build.gradle +++ /dev/null @@ -1,96 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTexturecubemapArray" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/texturecubemaparray' - into 'assets/shaders/glsl/texturecubemaparray' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sphere.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'teapot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'torusknot.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'venus.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'cubemap_array.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/texturecubemaparray/src/main/AndroidManifest.xml b/android/examples/texturecubemaparray/src/main/AndroidManifest.xml deleted file mode 100644 index 2e087df9..00000000 --- a/android/examples/texturecubemaparray/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/texturecubemaparray/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/texturecubemaparray/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/texturecubemaparray/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/texturemipmapgen/CMakeLists.txt b/android/examples/texturemipmapgen/CMakeLists.txt deleted file mode 100644 index 8a56121b..00000000 --- a/android/examples/texturemipmapgen/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME texturemipmapgen) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/texturemipmapgen/build.gradle b/android/examples/texturemipmapgen/build.gradle deleted file mode 100644 index 8249c6a3..00000000 --- a/android/examples/texturemipmapgen/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTexturemipmapgen" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/texturemipmapgen' - into 'assets/shaders/glsl/texturemipmapgen' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'tunnel_cylinder.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'metalplate_nomips_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/texturemipmapgen/src/main/AndroidManifest.xml b/android/examples/texturemipmapgen/src/main/AndroidManifest.xml deleted file mode 100644 index 8c914217..00000000 --- a/android/examples/texturemipmapgen/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/texturemipmapgen/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/texturemipmapgen/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/texturemipmapgen/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/texturesparseresidency/CMakeLists.txt b/android/examples/texturesparseresidency/CMakeLists.txt deleted file mode 100644 index 9f5d6571..00000000 --- a/android/examples/texturesparseresidency/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME texturesparseresidency) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/texturesparseresidency/build.gradle b/android/examples/texturesparseresidency/build.gradle deleted file mode 100644 index 505f4700..00000000 --- a/android/examples/texturesparseresidency/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTexturesparseresidency" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/texturesparseresidency' - into 'assets/shaders/glsl/texturesparseresidency' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'plane.gltf' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/texturesparseresidency/src/main/AndroidManifest.xml b/android/examples/texturesparseresidency/src/main/AndroidManifest.xml deleted file mode 100644 index cc16f382..00000000 --- a/android/examples/texturesparseresidency/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/texturesparseresidency/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/texturesparseresidency/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/texturesparseresidency/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/timelinesemaphore/CMakeLists.txt b/android/examples/timelinesemaphore/CMakeLists.txt deleted file mode 100644 index 2d2bd833..00000000 --- a/android/examples/timelinesemaphore/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME timelinesemaphore) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/timelinesemaphore/build.gradle b/android/examples/timelinesemaphore/build.gradle deleted file mode 100644 index 3da087d6..00000000 --- a/android/examples/timelinesemaphore/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTimelinesemaphore" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/computenbody' - into 'assets/shaders/glsl/computenbody' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'particle01_rgba.ktx' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'particle_gradient_rgba.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/timelinesemaphore/src/main/AndroidManifest.xml b/android/examples/timelinesemaphore/src/main/AndroidManifest.xml deleted file mode 100644 index 821c8f6b..00000000 --- a/android/examples/timelinesemaphore/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/timelinesemaphore/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/timelinesemaphore/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/timelinesemaphore/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/triangle/CMakeLists.txt b/android/examples/triangle/CMakeLists.txt deleted file mode 100644 index 13727990..00000000 --- a/android/examples/triangle/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME triangle) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/triangle/build.gradle b/android/examples/triangle/build.gradle deleted file mode 100644 index 5412f397..00000000 --- a/android/examples/triangle/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTriangle" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/triangle' - into 'assets/shaders/glsl/triangle' - include '*.*' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/triangle/src/main/AndroidManifest.xml b/android/examples/triangle/src/main/AndroidManifest.xml deleted file mode 100644 index 020c6835..00000000 --- a/android/examples/triangle/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/triangle/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/triangle/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/triangle/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/trianglevulkan13/CMakeLists.txt b/android/examples/trianglevulkan13/CMakeLists.txt deleted file mode 100644 index e2b2f44e..00000000 --- a/android/examples/trianglevulkan13/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME trianglevulkan13) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/trianglevulkan13/build.gradle b/android/examples/trianglevulkan13/build.gradle deleted file mode 100644 index 542a3d29..00000000 --- a/android/examples/trianglevulkan13/build.gradle +++ /dev/null @@ -1,59 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanTrianglevulkan13" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/triangle' - into 'assets/shaders/glsl/triangle' - include '*.*' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/trianglevulkan13/src/main/AndroidManifest.xml b/android/examples/trianglevulkan13/src/main/AndroidManifest.xml deleted file mode 100644 index 206434ef..00000000 --- a/android/examples/trianglevulkan13/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/trianglevulkan13/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/trianglevulkan13/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/trianglevulkan13/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/variablerateshading/CMakeLists.txt b/android/examples/variablerateshading/CMakeLists.txt deleted file mode 100644 index c6536178..00000000 --- a/android/examples/variablerateshading/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME variablerateshading) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/variablerateshading/build.gradle b/android/examples/variablerateshading/build.gradle deleted file mode 100644 index 5422e6d6..00000000 --- a/android/examples/variablerateshading/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanVariablerateshading" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/variablerateshading' - into 'assets/shaders/glsl/variablerateshading' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models/sponza' - into 'assets/models/sponza' - include '*.*' - } - -} - -preBuild.dependsOn copyTask diff --git a/android/examples/variablerateshading/src/main/AndroidManifest.xml b/android/examples/variablerateshading/src/main/AndroidManifest.xml deleted file mode 100644 index 5f51b1dd..00000000 --- a/android/examples/variablerateshading/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/variablerateshading/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/variablerateshading/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/variablerateshading/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/vertexattributes/CMakeLists.txt b/android/examples/vertexattributes/CMakeLists.txt deleted file mode 100644 index ff8e61bb..00000000 --- a/android/examples/vertexattributes/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME vertexattributes) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/vertexattributes/build.gradle b/android/examples/vertexattributes/build.gradle deleted file mode 100644 index 501ad04f..00000000 --- a/android/examples/vertexattributes/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanVertexattributes" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/vertexattributes' - into 'assets/shaders/glsl/vertexattributes' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models/sponza' - into 'assets/models/sponza' - include '*.*' - } - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/vertexattributes/src/main/AndroidManifest.xml b/android/examples/vertexattributes/src/main/AndroidManifest.xml deleted file mode 100644 index c78888df..00000000 --- a/android/examples/vertexattributes/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/vertexattributes/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/vertexattributes/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/vertexattributes/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/viewportarray/CMakeLists.txt b/android/examples/viewportarray/CMakeLists.txt deleted file mode 100644 index bf64ad1f..00000000 --- a/android/examples/viewportarray/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME viewportarray) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/viewportarray/build.gradle b/android/examples/viewportarray/build.gradle deleted file mode 100644 index fe35d477..00000000 --- a/android/examples/viewportarray/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanViewportarray" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/viewportarray' - into 'assets/shaders/glsl/viewportarray' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'sampleroom.gltf' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/viewportarray/src/main/AndroidManifest.xml b/android/examples/viewportarray/src/main/AndroidManifest.xml deleted file mode 100644 index 921b4da7..00000000 --- a/android/examples/viewportarray/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/viewportarray/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/viewportarray/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/viewportarray/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/examples/vulkanscene/CMakeLists.txt b/android/examples/vulkanscene/CMakeLists.txt deleted file mode 100644 index 9a166313..00000000 --- a/android/examples/vulkanscene/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) - - - -set(NAME vulkanscene) - -set(SRC_DIR ../../../examples/${NAME}) -set(BASE_DIR ../../../base) -set(EXTERNAL_DIR ../../../external) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DVK_USE_PLATFORM_ANDROID_KHR -DVK_NO_PROTOTYPES") - -file(GLOB EXAMPLE_SRC "${SRC_DIR}/*.cpp") - -add_library(native-lib SHARED ${EXAMPLE_SRC}) - -add_library(native-app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - -add_subdirectory(../base ${CMAKE_SOURCE_DIR}/../base) - -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") - -include_directories(${BASE_DIR}) -include_directories(${EXTERNAL_DIR}) -include_directories(${EXTERNAL_DIR}/glm) -include_directories(${EXTERNAL_DIR}/imgui) -include_directories(${EXTERNAL_DIR}/tinygltf) -include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - -target_link_libraries( - native-lib - native-app-glue - libbase - android - log - z -) diff --git a/android/examples/vulkanscene/build.gradle b/android/examples/vulkanscene/build.gradle deleted file mode 100644 index 3a0307a9..00000000 --- a/android/examples/vulkanscene/build.gradle +++ /dev/null @@ -1,90 +0,0 @@ -apply plugin: 'com.android.application' -apply from: '../gradle/outputfilename.gradle' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "de.saschawillems.vulkanVulkanscene" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - ndk { - abiFilters rootProject.ext.abiFilters - } - externalNativeBuild { - cmake { - cppFlags "-std=c++14" - arguments "-DANDROID_STL=c++_shared", '-DANDROID_TOOLCHAIN=clang' - } - } - } - sourceSets { - main.assets.srcDirs = ['assets'] - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -task copyTask { - copy { - from '../../common/res/drawable' - into "src/main/res/drawable" - include 'icon.png' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/base' - into 'assets/shaders/glsl/base' - include '*.spv' - } - - copy { - from rootProject.ext.shaderPath + 'glsl/vulkanscene' - into 'assets/shaders/glsl/vulkanscene' - include '*.*' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'vulkanscenelogos.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'vulkanscenebackground.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'vulkanscenemodels.gltf' - } - - copy { - from rootProject.ext.assetPath + 'models' - into 'assets/models' - include 'cube.gltf' - } - - copy { - from rootProject.ext.assetPath + 'textures' - into 'assets/textures' - include 'cubemap_vulkan.ktx' - } - - -} - -preBuild.dependsOn copyTask \ No newline at end of file diff --git a/android/examples/vulkanscene/src/main/AndroidManifest.xml b/android/examples/vulkanscene/src/main/AndroidManifest.xml deleted file mode 100644 index 9cb8a7a3..00000000 --- a/android/examples/vulkanscene/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/examples/vulkanscene/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java b/android/examples/vulkanscene/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java deleted file mode 100644 index 12e14fc6..00000000 --- a/android/examples/vulkanscene/src/main/java/de/saschawillems/vulkanSample/VulkanActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2018 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ -package de.saschawillems.vulkanSample; - -import android.app.AlertDialog; -import android.app.NativeActivity; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; - -import java.util.concurrent.Semaphore; - -public class VulkanActivity extends NativeActivity { - - static { - // Load native library - System.loadLibrary("native-lib"); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - // Use a semaphore to create a modal dialog - - private final Semaphore semaphore = new Semaphore(0, true); - - public void showAlert(final String message) - { - final VulkanActivity activity = this; - - ApplicationInfo applicationInfo = activity.getApplicationInfo(); - final String applicationName = applicationInfo.nonLocalizedLabel.toString(); - - this.runOnUiThread(new Runnable() { - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Dialog_Alert); - builder.setTitle(applicationName); - builder.setMessage(message); - builder.setPositiveButton("Close", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - semaphore.release(); - } - }); - builder.setCancelable(false); - AlertDialog dialog = builder.create(); - dialog.show(); - } - }); - try { - semaphore.acquire(); - } - catch (InterruptedException e) { } - } -} diff --git a/android/gradle.properties b/android/gradle.properties deleted file mode 100644 index 2b474b57..00000000 --- a/android/gradle.properties +++ /dev/null @@ -1,17 +0,0 @@ -## For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx1024m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -# -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -#Sun May 28 17:34:07 CST 2023 -android.defaults.buildfeatures.buildconfig=true -android.nonFinalResIds=false -android.nonTransitiveRClass=false -org.gradle.jvmargs=-Xmx4096M diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7454180f..00000000 Binary files a/android/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 328f7a40..00000000 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Thu Oct 10 17:55:02 CEST 2024 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/android/gradlew b/android/gradlew deleted file mode 100755 index c53aefaa..00000000 --- a/android/gradlew +++ /dev/null @@ -1,234 +0,0 @@ -#!/bin/sh - -# -# Copyright 2015-2021 the original authors. -# -# 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 -# -# https://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. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions $var, ${var}, ${var:-default}, ${var+SET}, -# ${var#prefix}, ${var%suffix}, and $( cmd ); -# * compound commands having a testable exit status, especially case; -# * various built-in commands including command, set, and ulimit. -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat deleted file mode 100644 index 107acd32..00000000 --- a/android/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/android/settings.gradle b/android/settings.gradle deleted file mode 100644 index 74697331..00000000 --- a/android/settings.gradle +++ /dev/null @@ -1,9 +0,0 @@ -file('examples').eachDir { sub -> - if (sub.name != '_template') { - if (file("examples/$sub.name/build.gradle").exists()) { - println("Adding project $sub.name") - include ":$sub.name" - project(":$sub.name").projectDir = new File("examples/$sub.name") - } - } -} diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 90112062..69e66e4a 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -1,8 +1,31 @@ -# Copyright (c) 2016-2025, Sascha Willems -# SPDX-License-Identifier: MIT +# Procedural 3D Engine - Base Library +# Copyright (c) 2025 Your Project +# Licensed under the MIT License +# Based on Vulkan examples by Sascha Willems (MIT License) -file(GLOB BASE_SRC "*.cpp" "*.hpp" "*.h" "../external/imgui/*.cpp") -file(GLOB BASE_HEADERS "*.hpp" "*.h") +file(GLOB_RECURSE BASE_SRC + "*.cpp" + "*.hpp" + "*.h" + "device/*.cpp" + "device/*.h" + "memory/*.cpp" + "memory/*.h" + "core/*.cpp" + "core/*.hpp" + "core/*.h" + "foundation/*.cpp" + "foundation/*.h" +) +file(GLOB_RECURSE BASE_HEADERS + "*.hpp" + "*.h" + "device/*.h" + "memory/*.h" + "core/*.hpp" + "core/*.h" + "foundation/*.h" +) set(KTX_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../external/ktx) set(KTX_SOURCES diff --git a/base/VulkanAndroid.cpp b/base/VulkanAndroid.cpp deleted file mode 100644 index 43d8c1c7..00000000 --- a/base/VulkanAndroid.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* -* Android Vulkan function pointer loader -* -* Copyright (C) 2016-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "VulkanAndroid.h" - -#if defined(__ANDROID__) - #include - #include - #include - -android_app* androidApp; - -PFN_vkCreateInstance vkCreateInstance; -PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; -PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; -PFN_vkCreateDevice vkCreateDevice; -PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; -PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; -PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2; -PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; -PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties; -PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties; -PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures; -PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2; -PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; -PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; -PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; -PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; -PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; -PFN_vkCreateShaderModule vkCreateShaderModule; -PFN_vkCreateBuffer vkCreateBuffer; -PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; -PFN_vkMapMemory vkMapMemory; -PFN_vkUnmapMemory vkUnmapMemory; -PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; -PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges; -PFN_vkBindBufferMemory vkBindBufferMemory; -PFN_vkDestroyBuffer vkDestroyBuffer; -PFN_vkAllocateMemory vkAllocateMemory; -PFN_vkBindImageMemory vkBindImageMemory; -PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout; -PFN_vkCmdCopyBuffer vkCmdCopyBuffer; -PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; -PFN_vkCmdCopyImage vkCmdCopyImage; -PFN_vkCmdBlitImage vkCmdBlitImage; -PFN_vkCmdClearAttachments vkCmdClearAttachments; -PFN_vkCreateSampler vkCreateSampler; -PFN_vkDestroySampler vkDestroySampler; -PFN_vkDestroyImage vkDestroyImage; -PFN_vkFreeMemory vkFreeMemory; -PFN_vkCreateRenderPass vkCreateRenderPass; -PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; -PFN_vkCmdEndRenderPass vkCmdEndRenderPass; -PFN_vkCmdNextSubpass vkCmdNextSubpass; -PFN_vkCmdExecuteCommands vkCmdExecuteCommands; -PFN_vkCmdClearColorImage vkCmdClearColorImage; -PFN_vkCreateImage vkCreateImage; -PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; -PFN_vkCreateImageView vkCreateImageView; -PFN_vkDestroyImageView vkDestroyImageView; -PFN_vkCreateSemaphore vkCreateSemaphore; -PFN_vkDestroySemaphore vkDestroySemaphore; -PFN_vkCreateFence vkCreateFence; -PFN_vkDestroyFence vkDestroyFence; -PFN_vkWaitForFences vkWaitForFences; -PFN_vkResetFences vkResetFences; -PFN_vkResetDescriptorPool vkResetDescriptorPool; -PFN_vkCreateCommandPool vkCreateCommandPool; -PFN_vkDestroyCommandPool vkDestroyCommandPool; -PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; -PFN_vkBeginCommandBuffer vkBeginCommandBuffer; -PFN_vkEndCommandBuffer vkEndCommandBuffer; -PFN_vkGetDeviceQueue vkGetDeviceQueue; -PFN_vkQueueSubmit vkQueueSubmit; -PFN_vkQueueWaitIdle vkQueueWaitIdle; -PFN_vkDeviceWaitIdle vkDeviceWaitIdle; -PFN_vkCreateFramebuffer vkCreateFramebuffer; -PFN_vkCreatePipelineCache vkCreatePipelineCache; -PFN_vkCreatePipelineLayout vkCreatePipelineLayout; -PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines; -PFN_vkCreateComputePipelines vkCreateComputePipelines; -PFN_vkCreateDescriptorPool vkCreateDescriptorPool; -PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout; -PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets; -PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets; -PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets; -PFN_vkCmdBindPipeline vkCmdBindPipeline; -PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers; -PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer; -PFN_vkCmdSetViewport vkCmdSetViewport; -PFN_vkCmdSetScissor vkCmdSetScissor; -PFN_vkCmdSetLineWidth vkCmdSetLineWidth; -PFN_vkCmdSetDepthBias vkCmdSetDepthBias; -PFN_vkCmdPushConstants vkCmdPushConstants; -PFN_vkCmdDrawIndexed vkCmdDrawIndexed; -PFN_vkCmdDraw vkCmdDraw; -PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect; -PFN_vkCmdDrawIndirect vkCmdDrawIndirect; -PFN_vkCmdDispatch vkCmdDispatch; -PFN_vkDestroyPipeline vkDestroyPipeline; -PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout; -PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout; -PFN_vkDestroyDevice vkDestroyDevice; -PFN_vkDestroyInstance vkDestroyInstance; -PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool; -PFN_vkFreeCommandBuffers vkFreeCommandBuffers; -PFN_vkDestroyRenderPass vkDestroyRenderPass; -PFN_vkDestroyFramebuffer vkDestroyFramebuffer; -PFN_vkDestroyShaderModule vkDestroyShaderModule; -PFN_vkDestroyPipelineCache vkDestroyPipelineCache; -PFN_vkCreateQueryPool vkCreateQueryPool; -PFN_vkDestroyQueryPool vkDestroyQueryPool; -PFN_vkGetQueryPoolResults vkGetQueryPoolResults; -PFN_vkCmdBeginQuery vkCmdBeginQuery; -PFN_vkCmdEndQuery vkCmdEndQuery; -PFN_vkCmdResetQueryPool vkCmdResetQueryPool; -PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults; -PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties; -PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements; -PFN_vkQueueBindSparse vkQueueBindSparse; -PFN_vkCmdBeginRendering vkCmdBeginRendering; -PFN_vkCmdEndRendering vkCmdEndRendering; - -PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; -PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; -PFN_vkCmdFillBuffer vkCmdFillBuffer; - -PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; -PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; -PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; -PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; -PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; -PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; -PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; -PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; -PFN_vkQueuePresentKHR vkQueuePresentKHR; - -PFN_vkResetCommandBuffer vkResetCommandBuffer; - -PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties; - -int32_t vks::android::screenDensity; - -void *libVulkan; - -namespace vks -{ - namespace android - { - // Dynamically load Vulkan library and base function pointers - bool loadVulkanLibrary() - { - __android_log_print(ANDROID_LOG_INFO, "vulkanandroid", "Loading libvulkan.so...\n"); - - // Load vulkan library - libVulkan = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); - if (!libVulkan) - { - __android_log_print(ANDROID_LOG_INFO, "vulkanandroid", "Could not load vulkan library : %s!\n", dlerror()); - return false; - } - - // Load base function pointers - vkEnumerateInstanceExtensionProperties = reinterpret_cast(dlsym(libVulkan, "vkEnumerateInstanceExtensionProperties")); - vkEnumerateInstanceLayerProperties = reinterpret_cast(dlsym(libVulkan, "vkEnumerateInstanceLayerProperties")); - vkCreateInstance = reinterpret_cast(dlsym(libVulkan, "vkCreateInstance")); - vkGetInstanceProcAddr = reinterpret_cast(dlsym(libVulkan, "vkGetInstanceProcAddr")); - vkGetDeviceProcAddr = reinterpret_cast(dlsym(libVulkan, "vkGetDeviceProcAddr")); - - return true; - } - - // Load instance based Vulkan function pointers - void loadVulkanFunctions(VkInstance instance) - { - __android_log_print(ANDROID_LOG_INFO, "vulkanandroid", "Loading instance based function pointers...\n"); - - vkEnumeratePhysicalDevices = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices")); - vkGetPhysicalDeviceProperties = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties")); - vkGetPhysicalDeviceProperties2 = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2")); - vkEnumerateDeviceLayerProperties = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkEnumerateDeviceLayerProperties")); - vkEnumerateDeviceExtensionProperties = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkEnumerateDeviceExtensionProperties")); - vkGetPhysicalDeviceQueueFamilyProperties = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties")); - vkGetPhysicalDeviceFeatures = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures")); - vkGetPhysicalDeviceFeatures2 = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2")); - vkCreateDevice = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateDevice")); - vkGetPhysicalDeviceFormatProperties = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties")); - vkGetPhysicalDeviceMemoryProperties = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties")); - - vkCmdPipelineBarrier = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdPipelineBarrier")); - vkCreateShaderModule = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateShaderModule")); - - vkCreateBuffer = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateBuffer")); - vkGetBufferMemoryRequirements = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetBufferMemoryRequirements")); - vkMapMemory = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkMapMemory")); - vkUnmapMemory = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkUnmapMemory")); - vkFlushMappedMemoryRanges = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkFlushMappedMemoryRanges")); - vkInvalidateMappedMemoryRanges = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkInvalidateMappedMemoryRanges")); - vkBindBufferMemory = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkBindBufferMemory")); - vkDestroyBuffer = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyBuffer")); - - vkAllocateMemory = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkAllocateMemory")); - vkFreeMemory = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkFreeMemory")); - vkCreateRenderPass = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateRenderPass")); - vkCmdBeginRenderPass = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBeginRenderPass")); - vkCmdEndRenderPass = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdEndRenderPass")); - vkCmdNextSubpass = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdNextSubpass")); - vkCmdExecuteCommands = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdExecuteCommands")); - vkCmdClearColorImage = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdClearColorImage")); - - vkCreateImage = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateImage")); - vkGetImageMemoryRequirements = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetImageMemoryRequirements")); - vkCreateImageView = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateImageView")); - vkDestroyImageView = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyImageView")); - vkBindImageMemory = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkBindImageMemory")); - vkGetImageSubresourceLayout = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetImageSubresourceLayout")); - vkCmdCopyImage = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdCopyImage")); - vkCmdBlitImage = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBlitImage")); - vkDestroyImage = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyImage")); - - vkCmdClearAttachments = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdClearAttachments")); - - vkCmdCopyBuffer = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdCopyBuffer")); - vkCmdCopyBufferToImage = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdCopyBufferToImage")); - - vkCreateSampler = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateSampler")); - vkDestroySampler = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroySampler"));; - - vkCreateSemaphore = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateSemaphore")); - vkDestroySemaphore = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroySemaphore")); - - vkCreateFence = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateFence")); - vkDestroyFence = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyFence")); - vkWaitForFences = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkWaitForFences")); - vkResetFences = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkResetFences"));; - vkResetDescriptorPool = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkResetDescriptorPool")); - - vkCreateCommandPool = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateCommandPool")); - vkDestroyCommandPool = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyCommandPool"));; - - vkAllocateCommandBuffers = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkAllocateCommandBuffers")); - vkBeginCommandBuffer = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkBeginCommandBuffer")); - vkEndCommandBuffer = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkEndCommandBuffer")); - - vkGetDeviceQueue = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetDeviceQueue")); - vkQueueSubmit = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkQueueSubmit")); - vkQueueWaitIdle = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkQueueWaitIdle")); - - vkDeviceWaitIdle = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDeviceWaitIdle")); - - vkCreateFramebuffer = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateFramebuffer")); - - vkCreatePipelineCache = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreatePipelineCache")); - vkCreatePipelineLayout = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreatePipelineLayout")); - vkCreateGraphicsPipelines = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateGraphicsPipelines")); - vkCreateComputePipelines = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateComputePipelines")); - - vkCreateDescriptorPool = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateDescriptorPool")); - vkCreateDescriptorSetLayout = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateDescriptorSetLayout")); - - vkAllocateDescriptorSets = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkAllocateDescriptorSets")); - vkUpdateDescriptorSets = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkUpdateDescriptorSets")); - - vkCmdBindDescriptorSets = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBindDescriptorSets")); - vkCmdBindPipeline = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBindPipeline")); - vkCmdBindVertexBuffers = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBindVertexBuffers")); - vkCmdBindIndexBuffer = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBindIndexBuffer")); - - vkCmdSetViewport = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdSetViewport")); - vkCmdSetScissor = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdSetScissor")); - vkCmdSetLineWidth = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdSetLineWidth")); - vkCmdSetDepthBias = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdSetDepthBias")); - vkCmdPushConstants = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdPushConstants"));; - - vkCmdDrawIndexed = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdDrawIndexed")); - vkCmdDraw = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdDraw")); - vkCmdDrawIndexedIndirect = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirect")); - vkCmdDrawIndirect = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdDrawIndirect")); - vkCmdDispatch = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdDispatch")); - - vkDestroyPipeline = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyPipeline")); - vkDestroyPipelineLayout = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyPipelineLayout"));; - vkDestroyDescriptorSetLayout = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyDescriptorSetLayout")); - vkDestroyDevice = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyDevice")); - vkDestroyInstance = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyInstance")); - vkDestroyDescriptorPool = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyDescriptorPool")); - vkFreeCommandBuffers = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkFreeCommandBuffers")); - vkDestroyRenderPass = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyRenderPass")); - vkDestroyFramebuffer = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyFramebuffer")); - vkDestroyShaderModule = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyShaderModule")); - vkDestroyPipelineCache = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyPipelineCache")); - - vkCreateQueryPool = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateQueryPool")); - vkDestroyQueryPool = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyQueryPool")); - vkGetQueryPoolResults = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetQueryPoolResults")); - - vkCmdBeginQuery = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBeginQuery")); - vkCmdEndQuery = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdEndQuery")); - vkCmdResetQueryPool = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdResetQueryPool")); - vkCmdCopyQueryPoolResults = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdCopyQueryPoolResults")); - - vkGetPhysicalDeviceSparseImageFormatProperties = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties")); - vkGetImageSparseMemoryRequirements = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetImageSparseMemoryRequirements")); - vkQueueBindSparse = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkQueueBindSparse")); - - vkCmdBeginRendering = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBeginRendering")); - vkCmdEndRendering = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdEndRendering")); - - vkCreateAndroidSurfaceKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateAndroidSurfaceKHR")); - vkDestroySurfaceKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR")); - - vkCmdFillBuffer = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdFillBuffer")); - - vkGetPhysicalDeviceSurfaceSupportKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR")); - vkGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR")); - vkGetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR")); - vkGetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR")); - vkCreateSwapchainKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateSwapchainKHR")); - vkDestroySwapchainKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroySwapchainKHR")); - vkGetSwapchainImagesKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetSwapchainImagesKHR")); - vkAcquireNextImageKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkAcquireNextImageKHR")); - vkQueuePresentKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkQueuePresentKHR")); - - vkResetCommandBuffer = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkResetCommandBuffer")); - - vkGetPhysicalDeviceImageFormatProperties = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties")); - } - - void freeVulkanLibrary() - { - dlclose(libVulkan); - } - - void getDeviceConfig() - { - // Screen density - AConfiguration* config = AConfiguration_new(); - AConfiguration_fromAssetManager(config, androidApp->activity->assetManager); - vks::android::screenDensity = AConfiguration_getDensity(config); - AConfiguration_delete(config); - } - - // Displays a native alert dialog using JNI - void showAlert(const char* message) { - JNIEnv* jni; - androidApp->activity->vm->AttachCurrentThread(&jni, NULL); - - jstring jmessage = jni->NewStringUTF(message); - - jclass clazz = jni->GetObjectClass(androidApp->activity->clazz); - // Signature has to match java implementation (arguments) - jmethodID methodID = jni->GetMethodID(clazz, "showAlert", "(Ljava/lang/String;)V"); - jni->CallVoidMethod(androidApp->activity->clazz, methodID, jmessage); - jni->DeleteLocalRef(jmessage); - - androidApp->activity->vm->DetachCurrentThread(); - } - } -} - -#endif diff --git a/base/VulkanAndroid.h b/base/VulkanAndroid.h deleted file mode 100644 index f3201bde..00000000 --- a/base/VulkanAndroid.h +++ /dev/null @@ -1,198 +0,0 @@ -/* -* Android Vulkan function pointer prototypes -* -* Copyright (C) 2016-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#pragma once - -#ifndef VULKANANDROID_H -#define VULKANANDROID_H - -// Vulkan needs to be loaded dynamically on android -// While SDK 26 (and up) come with a loader, we also want to support older devices, so we manually load function pointers - -#pragma once - -#ifndef VULKANANDROID_HPP -#define VULKANANDROID_HPP - -#include "vulkan/vulkan.h" - -#if defined(__ANDROID__) - -#include -#include -#include -#include -#include - -// Global reference to android application object -extern android_app* androidApp; - -#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "vulkanExample", __VA_ARGS__)) -#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "vulkanExample", __VA_ARGS__)) -#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "vulkanExample", __VA_ARGS__)) -#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "vulkanExample", __VA_ARGS__)) - -// Function pointer prototypes -// Not complete, just the functions used in the caps viewer! -extern PFN_vkCreateInstance vkCreateInstance; -extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; -extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; -extern PFN_vkCreateDevice vkCreateDevice; -extern PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; -extern PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; -extern PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2; -extern PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; -extern PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties; -extern PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties; -extern PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures; -extern PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2; -extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; -extern PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; -extern PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; -extern PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; -extern PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; -extern PFN_vkCreateShaderModule vkCreateShaderModule; -extern PFN_vkCreateBuffer vkCreateBuffer; -extern PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; -extern PFN_vkMapMemory vkMapMemory; -extern PFN_vkUnmapMemory vkUnmapMemory; -extern PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; -extern PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges; -extern PFN_vkBindBufferMemory vkBindBufferMemory; -extern PFN_vkDestroyBuffer vkDestroyBuffer; -extern PFN_vkAllocateMemory vkAllocateMemory; -extern PFN_vkBindImageMemory vkBindImageMemory; -extern PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout; -extern PFN_vkCmdCopyBuffer vkCmdCopyBuffer; -extern PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; -extern PFN_vkCmdCopyImage vkCmdCopyImage; -extern PFN_vkCmdBlitImage vkCmdBlitImage; -extern PFN_vkCmdClearAttachments vkCmdClearAttachments; -extern PFN_vkCreateSampler vkCreateSampler; -extern PFN_vkDestroySampler vkDestroySampler; -extern PFN_vkDestroyImage vkDestroyImage; -extern PFN_vkFreeMemory vkFreeMemory; -extern PFN_vkCreateRenderPass vkCreateRenderPass; -extern PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; -extern PFN_vkCmdEndRenderPass vkCmdEndRenderPass; -extern PFN_vkCmdNextSubpass vkCmdNextSubpass; -extern PFN_vkCmdExecuteCommands vkCmdExecuteCommands; -extern PFN_vkCmdClearColorImage vkCmdClearColorImage; -extern PFN_vkCreateImage vkCreateImage; -extern PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; -extern PFN_vkCreateImageView vkCreateImageView; -extern PFN_vkDestroyImageView vkDestroyImageView; -extern PFN_vkCreateSemaphore vkCreateSemaphore; -extern PFN_vkDestroySemaphore vkDestroySemaphore; -extern PFN_vkCreateFence vkCreateFence; -extern PFN_vkDestroyFence vkDestroyFence; -extern PFN_vkWaitForFences vkWaitForFences; -extern PFN_vkResetFences vkResetFences; -extern PFN_vkResetDescriptorPool vkResetDescriptorPool; -extern PFN_vkCreateCommandPool vkCreateCommandPool; -extern PFN_vkDestroyCommandPool vkDestroyCommandPool; -extern PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; -extern PFN_vkBeginCommandBuffer vkBeginCommandBuffer; -extern PFN_vkEndCommandBuffer vkEndCommandBuffer; -extern PFN_vkGetDeviceQueue vkGetDeviceQueue; -extern PFN_vkQueueSubmit vkQueueSubmit; -extern PFN_vkQueueWaitIdle vkQueueWaitIdle; -extern PFN_vkDeviceWaitIdle vkDeviceWaitIdle; -extern PFN_vkCreateFramebuffer vkCreateFramebuffer; -extern PFN_vkCreatePipelineCache vkCreatePipelineCache; -extern PFN_vkCreatePipelineLayout vkCreatePipelineLayout; -extern PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines; -extern PFN_vkCreateComputePipelines vkCreateComputePipelines; -extern PFN_vkCreateDescriptorPool vkCreateDescriptorPool; -extern PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout; -extern PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets; -extern PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets; -extern PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets; -extern PFN_vkCmdBindPipeline vkCmdBindPipeline; -extern PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers; -extern PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer; -extern PFN_vkCmdSetViewport vkCmdSetViewport; -extern PFN_vkCmdSetScissor vkCmdSetScissor; -extern PFN_vkCmdSetLineWidth vkCmdSetLineWidth; -extern PFN_vkCmdSetDepthBias vkCmdSetDepthBias; -extern PFN_vkCmdPushConstants vkCmdPushConstants; -extern PFN_vkCmdDrawIndexed vkCmdDrawIndexed; -extern PFN_vkCmdDraw vkCmdDraw; -extern PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect; -extern PFN_vkCmdDrawIndirect vkCmdDrawIndirect; -extern PFN_vkCmdDispatch vkCmdDispatch; -extern PFN_vkDestroyPipeline vkDestroyPipeline; -extern PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout; -extern PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout; -extern PFN_vkDestroyDevice vkDestroyDevice; -extern PFN_vkDestroyInstance vkDestroyInstance; -extern PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool; -extern PFN_vkFreeCommandBuffers vkFreeCommandBuffers; -extern PFN_vkDestroyRenderPass vkDestroyRenderPass; -extern PFN_vkDestroyFramebuffer vkDestroyFramebuffer; -extern PFN_vkDestroyShaderModule vkDestroyShaderModule; -extern PFN_vkDestroyPipelineCache vkDestroyPipelineCache; -extern PFN_vkCreateQueryPool vkCreateQueryPool; -extern PFN_vkDestroyQueryPool vkDestroyQueryPool; -extern PFN_vkGetQueryPoolResults vkGetQueryPoolResults; -extern PFN_vkCmdBeginQuery vkCmdBeginQuery; -extern PFN_vkCmdEndQuery vkCmdEndQuery; -extern PFN_vkCmdResetQueryPool vkCmdResetQueryPool; -extern PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults; -extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties; -extern PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements; -extern PFN_vkQueueBindSparse vkQueueBindSparse; -extern PFN_vkCmdBeginRendering vkCmdBeginRendering; -extern PFN_vkCmdEndRendering vkCmdEndRendering; - -extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; -extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; -extern PFN_vkCmdFillBuffer vkCmdFillBuffer; - -extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; -extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; -extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; -extern PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; -extern PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; -extern PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; -extern PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; -extern PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; -extern PFN_vkQueuePresentKHR vkQueuePresentKHR; - -extern PFN_vkResetCommandBuffer vkResetCommandBuffer; - -extern PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties; - -namespace vks -{ - namespace android - { - /* @brief Touch control thresholds from Android NDK samples */ - const int32_t DOUBLE_TAP_TIMEOUT = 300 * 1000000; - const int32_t TAP_TIMEOUT = 180 * 1000000; - const int32_t DOUBLE_TAP_SLOP = 100; - const int32_t TAP_SLOP = 8; - - /** @brief Density of the device screen (in DPI) */ - extern int32_t screenDensity; - - bool loadVulkanLibrary(); - void loadVulkanFunctions(VkInstance instance); - void freeVulkanLibrary(); - void getDeviceConfig(); - void showAlert(const char* message); - } -} - -#endif - -#endif // VULKANANDROID_HPP - - -#endif // VULKANANDROID_H - \ No newline at end of file diff --git a/base/VulkanFrameBuffer.hpp b/base/VulkanFrameBuffer.hpp index d21c02cd..9e420a4a 100644 --- a/base/VulkanFrameBuffer.hpp +++ b/base/VulkanFrameBuffer.hpp @@ -12,8 +12,8 @@ #include #include #include "vulkan/vulkan.h" -#include "VulkanDevice.h" -#include "VulkanTools.h" +#include "device/VulkanDevice.h" +#include "core/VulkanTools.h" namespace vks { diff --git a/base/VulkanRaytracingSample.h b/base/VulkanRaytracingSample.h index 08b57e29..bcbaa46d 100644 --- a/base/VulkanRaytracingSample.h +++ b/base/VulkanRaytracingSample.h @@ -9,9 +9,9 @@ #pragma once #include "vulkan/vulkan.h" -#include "vulkanexamplebase.h" -#include "VulkanTools.h" -#include "VulkanDevice.h" +#include "foundation/vulkanexamplebase.h" +#include "core/VulkanTools.h" +#include "device/VulkanDevice.h" class VulkanRaytracingSample : public VulkanExampleBase { diff --git a/base/VulkanglTFModel.h b/base/VulkanglTFModel.h index 4aad677b..3bfd6fe8 100644 --- a/base/VulkanglTFModel.h +++ b/base/VulkanglTFModel.h @@ -21,7 +21,7 @@ #include #include "vulkan/vulkan.h" -#include "VulkanDevice.h" +#include "device/VulkanDevice.h" #include #include diff --git a/base/camera.hpp b/base/camera.hpp index 4838bde2..4fe9a4b9 100644 --- a/base/camera.hpp +++ b/base/camera.hpp @@ -22,29 +22,39 @@ private: { glm::mat4 currentMatrix = matrices.view; - glm::mat4 rotM = glm::mat4(1.0f); - glm::mat4 transM; + if (useOrbitMode && type == CameraType::lookat) { + // Orbit mode: position camera relative to orbit center using spherical coordinates + updateOrbitPosition(); + + // Use lookAt matrix for orbit mode + matrices.view = glm::lookAt(position, orbitCenter, glm::vec3(0.0f, 1.0f, 0.0f)); + viewPos = glm::vec4(position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f); + } else { + // Standard Sascha camera behavior + glm::mat4 rotM = glm::mat4(1.0f); + glm::mat4 transM; - rotM = glm::rotate(rotM, glm::radians(rotation.x * (flipY ? -1.0f : 1.0f)), glm::vec3(1.0f, 0.0f, 0.0f)); - rotM = glm::rotate(rotM, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - rotM = glm::rotate(rotM, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); + rotM = glm::rotate(rotM, glm::radians(rotation.x * (flipY ? -1.0f : 1.0f)), glm::vec3(1.0f, 0.0f, 0.0f)); + rotM = glm::rotate(rotM, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); + rotM = glm::rotate(rotM, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); - glm::vec3 translation = position; - if (flipY) { - translation.y *= -1.0f; + glm::vec3 translation = position; + if (flipY) { + translation.y *= -1.0f; + } + transM = glm::translate(glm::mat4(1.0f), translation); + + if (type == CameraType::firstperson) + { + matrices.view = rotM * transM; + } + else + { + matrices.view = transM * rotM; + } + + viewPos = glm::vec4(position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f); } - transM = glm::translate(glm::mat4(1.0f), translation); - - if (type == CameraType::firstperson) - { - matrices.view = rotM * transM; - } - else - { - matrices.view = transM * rotM; - } - - viewPos = glm::vec4(position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f); if (matrices.view != currentMatrix) { updated = true; @@ -58,6 +68,11 @@ public: glm::vec3 position = glm::vec3(); glm::vec4 viewPos = glm::vec4(); + // Orbit camera support + glm::vec3 orbitCenter = glm::vec3(0.0f); + float orbitDistance = 8.0f; + bool useOrbitMode = false; + float rotationSpeed = 1.0f; float movementSpeed = 1.0f; @@ -158,6 +173,61 @@ public: this->movementSpeed = movementSpeed; } + // Update camera position based on orbit center and current rotation + void updateOrbitPosition() + { + if (!useOrbitMode) return; + + // Convert Euler angles to spherical coordinates around orbit center + float pitch = glm::radians(rotation.x); + float yaw = glm::radians(rotation.y); + + // Calculate position relative to orbit center using spherical coordinates + float x = orbitDistance * cos(pitch) * cos(yaw); + float y = orbitDistance * sin(pitch); + float z = orbitDistance * cos(pitch) * sin(yaw); + + position = orbitCenter + glm::vec3(x, y, z); + } + + // Enable orbit mode and set orbit center + void setOrbitMode(glm::vec3 center, float distance) + { + orbitCenter = center; + orbitDistance = distance; + useOrbitMode = true; + updateViewMatrix(); + } + + // Disable orbit mode and return to standard camera + void disableOrbitMode() + { + useOrbitMode = false; + updateViewMatrix(); + } + + // Focus camera on an object using orbit mode + void focusOnObject(glm::vec3 objectCenter, float objectRadius) + { + // Calculate optimal viewing distance based on object radius and FOV + float halfFovRadians = glm::radians(fov * 0.5f); + float distance = objectRadius / glm::tan(halfFovRadians) * 2.5f; + distance = glm::max(distance, objectRadius * 3.0f); + + // Set orbit center to the object center + orbitCenter = objectCenter; + orbitDistance = distance; + useOrbitMode = true; + + // Set camera to a good viewing angle (slightly elevated and angled) + rotation.x = 15.0f; // Slight elevation + rotation.y = 30.0f; // Angled view + rotation.z = 0.0f; + + // Update position and view matrix + updateViewMatrix(); + } + void update(float deltaTime) { updated = false; diff --git a/base/VulkanDebug.cpp b/base/core/VulkanDebug.cpp similarity index 100% rename from base/VulkanDebug.cpp rename to base/core/VulkanDebug.cpp diff --git a/base/VulkanDebug.h b/base/core/VulkanDebug.h similarity index 100% rename from base/VulkanDebug.h rename to base/core/VulkanDebug.h diff --git a/base/VulkanInitializers.hpp b/base/core/VulkanInitializers.hpp similarity index 100% rename from base/VulkanInitializers.hpp rename to base/core/VulkanInitializers.hpp diff --git a/base/VulkanTools.cpp b/base/core/VulkanTools.cpp similarity index 100% rename from base/VulkanTools.cpp rename to base/core/VulkanTools.cpp diff --git a/base/VulkanTools.h b/base/core/VulkanTools.h similarity index 100% rename from base/VulkanTools.h rename to base/core/VulkanTools.h diff --git a/base/VulkanDevice.cpp b/base/device/VulkanDevice.cpp similarity index 99% rename from base/VulkanDevice.cpp rename to base/device/VulkanDevice.cpp index 8c1e9755..f76aca3a 100644 --- a/base/VulkanDevice.cpp +++ b/base/device/VulkanDevice.cpp @@ -12,7 +12,7 @@ // SRS - Enable beta extensions and make VK_KHR_portability_subset visible #define VK_ENABLE_BETA_EXTENSIONS #endif -#include +#include "VulkanDevice.h" #include namespace vks diff --git a/base/VulkanDevice.h b/base/device/VulkanDevice.h similarity index 97% rename from base/VulkanDevice.h rename to base/device/VulkanDevice.h index 87597687..70d1f739 100644 --- a/base/VulkanDevice.h +++ b/base/device/VulkanDevice.h @@ -10,8 +10,8 @@ #pragma once -#include "VulkanBuffer.h" -#include "VulkanTools.h" +#include "../memory/VulkanBuffer.h" +#include "../core/VulkanTools.h" #include "vulkan/vulkan.h" #include #include diff --git a/base/VulkanSwapChain.cpp b/base/device/VulkanSwapChain.cpp similarity index 100% rename from base/VulkanSwapChain.cpp rename to base/device/VulkanSwapChain.cpp diff --git a/base/VulkanSwapChain.h b/base/device/VulkanSwapChain.h similarity index 99% rename from base/VulkanSwapChain.h rename to base/device/VulkanSwapChain.h index cb1386a3..aa252972 100644 --- a/base/VulkanSwapChain.h +++ b/base/device/VulkanSwapChain.h @@ -17,7 +17,7 @@ #include #include -#include "VulkanTools.h" +#include "../core/VulkanTools.h" #ifdef __ANDROID__ #include "VulkanAndroid.h" diff --git a/base/VulkanUIOverlay.cpp b/base/foundation/VulkanUIOverlay.cpp similarity index 100% rename from base/VulkanUIOverlay.cpp rename to base/foundation/VulkanUIOverlay.cpp diff --git a/base/VulkanUIOverlay.h b/base/foundation/VulkanUIOverlay.h similarity index 94% rename from base/VulkanUIOverlay.h rename to base/foundation/VulkanUIOverlay.h index 1a4bf557..ee6730b9 100644 --- a/base/VulkanUIOverlay.h +++ b/base/foundation/VulkanUIOverlay.h @@ -17,10 +17,10 @@ #include #include -#include "VulkanTools.h" -#include "VulkanDebug.h" -#include "VulkanBuffer.h" -#include "VulkanDevice.h" +#include "../core/VulkanTools.h" +#include "../core/VulkanDebug.h" +#include "../memory/VulkanBuffer.h" +#include "../device/VulkanDevice.h" #include "../external/imgui/imgui.h" diff --git a/base/vulkanexamplebase.cpp b/base/foundation/vulkanexamplebase.cpp similarity index 99% rename from base/vulkanexamplebase.cpp rename to base/foundation/vulkanexamplebase.cpp index 87b3fde0..b08330b0 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/foundation/vulkanexamplebase.cpp @@ -1304,7 +1304,7 @@ HWND VulkanExampleBase::setupWindow(HINSTANCE hinstance, WNDPROC wndproc) SetWindowPos(window, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); } - ShowWindow(window, SW_SHOW); + ShowWindow(window, SW_MAXIMIZE); SetForegroundWindow(window); SetFocus(window); diff --git a/base/vulkanexamplebase.h b/base/foundation/vulkanexamplebase.h similarity index 97% rename from base/vulkanexamplebase.h rename to base/foundation/vulkanexamplebase.h index 7f742be5..40cba822 100644 --- a/base/vulkanexamplebase.h +++ b/base/foundation/vulkanexamplebase.h @@ -9,7 +9,8 @@ #pragma once #ifdef _WIN32 -#pragma comment(linker, "/subsystem:windows") +// Note: Removed /subsystem:windows pragma to allow console applications +// #pragma comment(linker, "/subsystem:windows") #include #include #include @@ -63,17 +64,17 @@ #include "CommandLineParser.hpp" #include "keycodes.hpp" -#include "VulkanTools.h" -#include "VulkanDebug.h" +#include "../core/VulkanTools.h" +#include "../core/VulkanDebug.h" #include "VulkanUIOverlay.h" -#include "VulkanSwapChain.h" -#include "VulkanBuffer.h" -#include "VulkanDevice.h" -#include "VulkanTexture.h" +#include "../device/VulkanSwapChain.h" +#include "../memory/VulkanBuffer.h" +#include "../device/VulkanDevice.h" +#include "../memory/VulkanTexture.h" -#include "VulkanInitializers.hpp" -#include "camera.hpp" -#include "benchmark.hpp" +#include "../core/VulkanInitializers.hpp" +#include "../camera.hpp" +#include "../benchmark.hpp" class VulkanExampleBase { @@ -163,8 +164,8 @@ public: bool prepared = false; bool resized = false; bool viewUpdated = false; - uint32_t width = 1280; - uint32_t height = 720; + uint32_t width = 1920; + uint32_t height = 1080; vks::UIOverlay ui; CommandLineParser commandLineParser; diff --git a/base/VulkanBuffer.cpp b/base/memory/VulkanBuffer.cpp similarity index 100% rename from base/VulkanBuffer.cpp rename to base/memory/VulkanBuffer.cpp diff --git a/base/VulkanBuffer.h b/base/memory/VulkanBuffer.h similarity index 97% rename from base/VulkanBuffer.h rename to base/memory/VulkanBuffer.h index bd2a421f..c2e4468a 100644 --- a/base/VulkanBuffer.h +++ b/base/memory/VulkanBuffer.h @@ -13,7 +13,7 @@ #include #include "vulkan/vulkan.h" -#include "VulkanTools.h" +#include "../core/VulkanTools.h" namespace vks { diff --git a/base/VulkanTexture.cpp b/base/memory/VulkanTexture.cpp similarity index 99% rename from base/VulkanTexture.cpp rename to base/memory/VulkanTexture.cpp index 01093b07..6e107ac5 100644 --- a/base/VulkanTexture.cpp +++ b/base/memory/VulkanTexture.cpp @@ -6,7 +6,7 @@ * This code is licensed under the MIT license(MIT) (http://opensource.org/licenses/MIT) */ -#include +#include "VulkanTexture.h" namespace vks { diff --git a/base/VulkanTexture.h b/base/memory/VulkanTexture.h similarity index 97% rename from base/VulkanTexture.h rename to base/memory/VulkanTexture.h index 09cf56f2..1601dec7 100644 --- a/base/VulkanTexture.h +++ b/base/memory/VulkanTexture.h @@ -19,8 +19,8 @@ #include #include "VulkanBuffer.h" -#include "VulkanDevice.h" -#include "VulkanTools.h" +#include "../device/VulkanDevice.h" +#include "../core/VulkanTools.h" #if defined(__ANDROID__) # include diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index baf7e7fa..c6f8ca88 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -87,100 +87,7 @@ function(buildExamples) endfunction(buildExamples) set(EXAMPLES - bloom - bufferdeviceaddress - computecloth - computecullandlod - computeheadless - computenbody - computeparticles - computeraytracing - computeshader - conditionalrender - conservativeraster - debugprintf - debugutils - deferred - deferredmultisampling - deferredshadows - descriptorbuffer - descriptorindexing - descriptorsets - displacement - distancefieldfonts - dynamicrendering - dynamicrenderingmultisampling - dynamicstate - dynamicuniformbuffer - gears - geometryshader - gltfloading - gltfscenerendering - gltfskinning - graphicspipelinelibrary - hdr - hostimagecopy imgui - indirectdraw - inlineuniformblocks - inputattachments - instancing - meshshader - multisampling - multithreading - multiview - negativeviewportheight - occlusionquery - offscreen - oit - parallaxmapping - particlesystem - pbrbasic - pbribl - pbrtexture - pipelines - pipelinestatistics - pushconstants - pushdescriptors - radialblur - rayquery - raytracingbasic - raytracingcallable - raytracinggltf - raytracingintersection - raytracingreflections - raytracingpositionfetch - raytracingsbtdata - raytracingshadows - raytracingtextures - renderheadless - screenshot - shaderobjects - shadowmapping - shadowmappingomni - shadowmappingcascade - specializationconstants - sphericalenvmapping - ssao - stencilbuffer - subpasses - terraintessellation - tessellation - textoverlay - texture - texture3d - texturearray - texturecubemap - texturecubemaparray - texturemipmapgen - texturesparseresidency - timelinesemaphore - triangle - trianglevulkan13 - variablerateshading - vertexattributes - viewportarray - vulkanscene ) buildExamples() diff --git a/examples/bloom/bloom.cpp b/examples/bloom/bloom.cpp deleted file mode 100644 index b4b27560..00000000 --- a/examples/bloom/bloom.cpp +++ /dev/null @@ -1,727 +0,0 @@ -/* -* Vulkan Example - Implements a separable two-pass fullscreen blur (also known as bloom) -* -* Copyright (C) 2016 - 2023 Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - - -// Offscreen frame buffer properties -#define FB_DIM 256 -#define FB_COLOR_FORMAT VK_FORMAT_R8G8B8A8_UNORM - -class VulkanExample : public VulkanExampleBase -{ -public: - bool bloom = true; - - vks::TextureCubeMap cubemap; - - struct { - vkglTF::Model ufo; - vkglTF::Model ufoGlow; - vkglTF::Model skyBox; - } models; - - struct { - vks::Buffer scene; - vks::Buffer skyBox; - vks::Buffer blurParams; - } uniformBuffers; - - struct UBO { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - }; - - struct UBOBlurParams { - float blurScale = 1.0f; - float blurStrength = 1.5f; - }; - - struct { - UBO scene, skyBox; - UBOBlurParams blurParams; - } ubos; - - struct { - VkPipeline blurVert; - VkPipeline blurHorz; - VkPipeline glowPass; - VkPipeline phongPass; - VkPipeline skyBox; - } pipelines; - - struct { - VkPipelineLayout blur; - VkPipelineLayout scene; - } pipelineLayouts; - - struct { - VkDescriptorSet blurVert; - VkDescriptorSet blurHorz; - VkDescriptorSet scene; - VkDescriptorSet skyBox; - } descriptorSets; - - struct { - VkDescriptorSetLayout blur; - VkDescriptorSetLayout scene; - } descriptorSetLayouts; - - // Framebuffer for offscreen rendering - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory mem; - VkImageView view; - }; - struct FrameBuffer { - VkFramebuffer framebuffer; - FrameBufferAttachment color, depth; - VkDescriptorImageInfo descriptor; - }; - struct OffscreenPass { - int32_t width, height; - VkRenderPass renderPass; - VkSampler sampler; - std::array framebuffers; - } offscreenPass; - - VulkanExample() : VulkanExampleBase() - { - title = "Bloom (offscreen rendering)"; - timerSpeed *= 0.5f; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -10.25f)); - camera.setRotation(glm::vec3(7.5f, -343.0f, 0.0f)); - camera.setPerspective(45.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - // Clean up used Vulkan resources - // Note : Inherited destructor cleans up resources stored in base class - - vkDestroySampler(device, offscreenPass.sampler, nullptr); - - // Frame buffer - for (auto& framebuffer : offscreenPass.framebuffers) - { - // Attachments - vkDestroyImageView(device, framebuffer.color.view, nullptr); - vkDestroyImage(device, framebuffer.color.image, nullptr); - vkFreeMemory(device, framebuffer.color.mem, nullptr); - vkDestroyImageView(device, framebuffer.depth.view, nullptr); - vkDestroyImage(device, framebuffer.depth.image, nullptr); - vkFreeMemory(device, framebuffer.depth.mem, nullptr); - - vkDestroyFramebuffer(device, framebuffer.framebuffer, nullptr); - } - vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); - - vkDestroyPipeline(device, pipelines.blurHorz, nullptr); - vkDestroyPipeline(device, pipelines.blurVert, nullptr); - vkDestroyPipeline(device, pipelines.phongPass, nullptr); - vkDestroyPipeline(device, pipelines.glowPass, nullptr); - vkDestroyPipeline(device, pipelines.skyBox, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayouts.blur , nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.scene, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.blur, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.scene, nullptr); - - // Uniform buffers - uniformBuffers.scene.destroy(); - uniformBuffers.skyBox.destroy(); - uniformBuffers.blurParams.destroy(); - - cubemap.destroy(); - } - - // Setup the offscreen framebuffer for rendering the mirrored scene - // The color attachment of this framebuffer will then be sampled from - void prepareOffscreenFramebuffer(FrameBuffer *frameBuf, VkFormat colorFormat, VkFormat depthFormat) - { - // Color attachment - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = colorFormat; - image.extent.width = FB_DIM; - image.extent.height = FB_DIM; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - // We will sample directly from the color attachment - image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = colorFormat; - colorImageView.flags = 0; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &frameBuf->color.image)); - vkGetImageMemoryRequirements(device, frameBuf->color.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &frameBuf->color.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, frameBuf->color.image, frameBuf->color.mem, 0)); - - colorImageView.image = frameBuf->color.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &frameBuf->color.view)); - - // Depth stencil attachment - image.format = depthFormat; - image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo(); - depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilView.format = depthFormat; - depthStencilView.flags = 0; - depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (vks::tools::formatHasStencil(depthFormat)) { - depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - depthStencilView.subresourceRange.baseMipLevel = 0; - depthStencilView.subresourceRange.levelCount = 1; - depthStencilView.subresourceRange.baseArrayLayer = 0; - depthStencilView.subresourceRange.layerCount = 1; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &frameBuf->depth.image)); - vkGetImageMemoryRequirements(device, frameBuf->depth.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &frameBuf->depth.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, frameBuf->depth.image, frameBuf->depth.mem, 0)); - - depthStencilView.image = frameBuf->depth.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &frameBuf->depth.view)); - - VkImageView attachments[2]; - attachments[0] = frameBuf->color.view; - attachments[1] = frameBuf->depth.view; - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = offscreenPass.renderPass; - fbufCreateInfo.attachmentCount = 2; - fbufCreateInfo.pAttachments = attachments; - fbufCreateInfo.width = FB_DIM; - fbufCreateInfo.height = FB_DIM; - fbufCreateInfo.layers = 1; - - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &frameBuf->framebuffer)); - - // Fill a descriptor for later use in a descriptor set - frameBuf->descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - frameBuf->descriptor.imageView = frameBuf->color.view; - frameBuf->descriptor.sampler = offscreenPass.sampler; - } - - // Prepare the offscreen framebuffers used for the vertical- and horizontal blur - void prepareOffscreen() - { - offscreenPass.width = FB_DIM; - offscreenPass.height = FB_DIM; - - // Find a suitable depth format - VkFormat fbDepthFormat; - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat); - assert(validDepthFormat); - - // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering - - std::array attchmentDescriptions = {}; - // Color attachment - attchmentDescriptions[0].format = FB_COLOR_FORMAT; - attchmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attchmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // Depth attachment - attchmentDescriptions[1].format = fbDepthFormat; - attchmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - VkAttachmentReference depthReference = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - subpassDescription.pDepthStencilAttachment = &depthReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Create the actual renderpass - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attchmentDescriptions.size()); - renderPassInfo.pAttachments = attchmentDescriptions.data(); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpassDescription; - renderPassInfo.dependencyCount = static_cast(dependencies.size()); - renderPassInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &offscreenPass.renderPass)); - - // Create sampler to sample from the color attachments - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 1.0f; - sampler.minLod = 0.0f; - sampler.maxLod = 1.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &offscreenPass.sampler)); - - // Create two frame buffers - prepareOffscreenFramebuffer(&offscreenPass.framebuffers[0], FB_COLOR_FORMAT, fbDepthFormat); - prepareOffscreenFramebuffer(&offscreenPass.framebuffers[1], FB_COLOR_FORMAT, fbDepthFormat); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - VkViewport viewport; - VkRect2D scissor; - - /* - The blur method used in this example is multi pass and renders the vertical blur first and then the horizontal one - While it's possible to blur in one pass, this method is widely used as it requires far less samples to generate the blur - */ - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - if (bloom) { - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = offscreenPass.renderPass; - renderPassBeginInfo.framebuffer = offscreenPass.framebuffers[0].framebuffer; - renderPassBeginInfo.renderArea.extent.width = offscreenPass.width; - renderPassBeginInfo.renderArea.extent.height = offscreenPass.height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - viewport = vks::initializers::viewport((float)offscreenPass.width, (float)offscreenPass.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - scissor = vks::initializers::rect2D(offscreenPass.width, offscreenPass.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - /* - First render pass: Render glow parts of the model (separate mesh) to an offscreen frame buffer - */ - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.glowPass); - - models.ufoGlow.draw(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - /* - Second render pass: Vertical blur - - Render contents of the first pass into a second framebuffer and apply a vertical blur - This is the first blur pass, the horizontal blur is applied when rendering on top of the scene - */ - - renderPassBeginInfo.framebuffer = offscreenPass.framebuffers[1].framebuffer; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.blur, 0, 1, &descriptorSets.blurVert, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.blurVert); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Third render pass: Scene rendering with applied vertical blur - - Renders the scene and the (vertically blurred) contents of the second framebuffer and apply a horizontal blur - - */ - { - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Skybox - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.skyBox, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skyBox); - models.skyBox.draw(drawCmdBuffers[i]); - - // 3D scene - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phongPass); - models.ufo.draw(drawCmdBuffers[i]); - - if (bloom) - { - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.blur, 0, 1, &descriptorSets.blurHorz, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.blurHorz); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.ufo.loadFromFile(getAssetPath() + "models/retroufo.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.ufoGlow.loadFromFile(getAssetPath() + "models/retroufo_glow.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.skyBox.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - cubemap.loadFromFile(getAssetPath() + "textures/cubemap_space.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 8), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 5); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layouts - std::vector setLayoutBindings; - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo; - - // Fullscreen blur - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), // Binding 0: Fragment shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) // Binding 1: Fragment shader image sampler - }; - descriptorSetLayoutCreateInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayouts.blur)); - - // Scene rendering - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), // Binding 2 : Fragment shader image sampler - }; - - descriptorSetLayoutCreateInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayouts.scene)); - - // Sets - VkDescriptorSetAllocateInfo descriptorSetAllocInfo; - std::vector writeDescriptorSets; - - // Full screen blur - // Vertical - descriptorSetAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.blur, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.blurVert)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.blurVert, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.blurParams.descriptor), // Binding 0: Fragment shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.blurVert, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &offscreenPass.framebuffers[0].descriptor), // Binding 1: Fragment shader texture sampler - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - // Horizontal - descriptorSetAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.blur, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.blurHorz)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.blurHorz, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.blurParams.descriptor), // Binding 0: Fragment shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.blurHorz, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &offscreenPass.framebuffers[1].descriptor), // Binding 1: Fragment shader texture sampler - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Scene rendering - descriptorSetAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.scene, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.scene)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor) // Binding 0: Vertex shader uniform buffer - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Skybox - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.skyBox)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.skyBox, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.skyBox.descriptor), // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.skyBox, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &cubemap.descriptor), // Binding 1: Fragment shader texture sampler - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layouts - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.blur, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.blur)); - - pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.scene, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.scene)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.blur, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Blur pipelines - shaderStages[0] = loadShader(getShadersPath() + "bloom/gaussblur.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "bloom/gaussblur.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Empty vertex input state - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCI.pVertexInputState = &emptyInputState; - pipelineCI.layout = pipelineLayouts.blur; - // Additive blending - blendAttachmentState.colorWriteMask = 0xF; - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; - - // Use specialization constants to select between horizontal and vertical blur - uint32_t blurdirection = 0; - VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t)); - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(uint32_t), &blurdirection); - shaderStages[1].pSpecializationInfo = &specializationInfo; - // Vertical blur pipeline - pipelineCI.renderPass = offscreenPass.renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.blurVert)); - // Horizontal blur pipeline - blurdirection = 1; - pipelineCI.renderPass = renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.blurHorz)); - - // Phong pass (3D model) - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal}); - pipelineCI.layout = pipelineLayouts.scene; - shaderStages[0] = loadShader(getShadersPath() + "bloom/phongpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "bloom/phongpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - blendAttachmentState.blendEnable = VK_FALSE; - depthStencilStateCI.depthWriteEnable = VK_TRUE; - rasterizationStateCI.cullMode = VK_CULL_MODE_BACK_BIT; - pipelineCI.renderPass = renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.phongPass)); - - // Color only pass (offscreen blur base) - shaderStages[0] = loadShader(getShadersPath() + "bloom/colorpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "bloom/colorpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - pipelineCI.renderPass = offscreenPass.renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.glowPass)); - - // Skybox (cubemap) - shaderStages[0] = loadShader(getShadersPath() + "bloom/skybox.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "bloom/skybox.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - depthStencilStateCI.depthWriteEnable = VK_FALSE; - rasterizationStateCI.cullMode = VK_CULL_MODE_FRONT_BIT; - pipelineCI.renderPass = renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.skyBox)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Phong and color pass vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.scene, - sizeof(ubos.scene))); - - // Blur parameters uniform buffers - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.blurParams, - sizeof(ubos.blurParams))); - - // Skybox - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.skyBox, - sizeof(ubos.skyBox))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffers.scene.map()); - VK_CHECK_RESULT(uniformBuffers.blurParams.map()); - VK_CHECK_RESULT(uniformBuffers.skyBox.map()); - - // Initialize uniform buffers - updateUniformBuffersScene(); - updateUniformBuffersBlur(); - } - - // Update uniform buffers for rendering the 3D scene - void updateUniformBuffersScene() - { - // UFO - ubos.scene.projection = camera.matrices.perspective; - ubos.scene.view = camera.matrices.view; - - ubos.scene.model = glm::translate(glm::mat4(1.0f), glm::vec3(sin(glm::radians(timer * 360.0f)) * 0.25f, -1.0f, cos(glm::radians(timer * 360.0f)) * 0.25f)); - ubos.scene.model = glm::rotate(ubos.scene.model, -sinf(glm::radians(timer * 360.0f)) * 0.15f, glm::vec3(1.0f, 0.0f, 0.0f)); - ubos.scene.model = glm::rotate(ubos.scene.model, glm::radians(timer * 360.0f), glm::vec3(0.0f, 1.0f, 0.0f)); - - memcpy(uniformBuffers.scene.mapped, &ubos.scene, sizeof(ubos.scene)); - - // Skybox - ubos.skyBox.projection = glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.1f, 256.0f); - ubos.skyBox.view = glm::mat4(glm::mat3(camera.matrices.view)); - ubos.skyBox.model = glm::mat4(1.0f); - - memcpy(uniformBuffers.skyBox.mapped, &ubos.skyBox, sizeof(ubos.skyBox)); - } - - // Update blur pass parameter uniform buffer - void updateUniformBuffersBlur() - { - memcpy(uniformBuffers.blurParams.mapped, &ubos.blurParams, sizeof(ubos.blurParams)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - prepareOffscreen(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (!paused || camera.updated) - { - updateUniformBuffersScene(); - } - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->checkBox("Bloom", &bloom)) { - buildCommandBuffers(); - } - if (overlay->inputFloat("Scale", &ubos.blurParams.blurScale, 0.1f, 2)) { - updateUniformBuffersBlur(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/bufferdeviceaddress/bufferdeviceaddress.cpp b/examples/bufferdeviceaddress/bufferdeviceaddress.cpp deleted file mode 100644 index 160bdc86..00000000 --- a/examples/bufferdeviceaddress/bufferdeviceaddress.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* -* Vulkan Example - Buffer device address -* -* This sample shows how to read data from a buffer device address (aka "reference") instead of using uniforms -* The application passes buffer device addresses to the shader via push constants, and the shader then simply reads the data behind that address -* See cube.vert for the shader side of things -* -* Copyright (C) 2024 by Sascha Willems - www.saschawillems.de -* -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool animate = true; - - struct Cube { - glm::mat4 modelMatrix; - vks::Buffer buffer; - glm::vec3 rotation; - VkDeviceAddress bufferDeviceAddress{}; - }; - std::array cubes{}; - - vks::Texture2D texture; - vkglTF::Model model; - - // Global matrices - struct Scene { - glm::mat4 mvp; - vks::Buffer buffer; - VkDeviceAddress bufferDeviceAddress{}; - } scene; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR{ VK_NULL_HANDLE }; - VkPhysicalDeviceBufferDeviceAddressFeatures enabledBufferDeviceAddresFeatures{}; - - // This sample passes the buffer references ("pointer") using push constants, the shader then reads data from that buffer address - struct PushConstantBlock { - // Reference to the global matrices - VkDeviceAddress sceneReference; - // Reference to the per model matrices - VkDeviceAddress modelReference; - }; - - VulkanExample() : VulkanExampleBase() - { - title = "Buffer device address"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -5.0f)); - - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - enabledInstanceExtensions.push_back(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_DEVICE_GROUP_EXTENSION_NAME); - - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - deviceCreatepNextChain = &enabledBufferDeviceAddresFeatures; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - texture.destroy(); - for (auto cube : cubes) { - cube.buffer.destroy(); - } - scene.buffer.destroy(); - } - } - - virtual void getEnabledFeatures() - { - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - }; - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - model.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - texture.loadFromFile(getAssetPath() + "textures/crate01_color_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - // We pass all data via buffer device addresses, so we only allocate descriptors for the images - void setupDescriptors() - { - // Pool - std::vector descriptorPoolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(descriptorPoolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &texture.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // The buffer addresses will be passed to the shader using push constants - // That way it's very easy to do a draw call, change the reference to another buffer (or part of that buffer) and do the next draw call using different data - VkPushConstantRange pushConstantRange{}; - pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - pushConstantRange.offset = 0; - pushConstantRange.size = sizeof(PushConstantBlock); - - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(); - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; - pipelineLayoutCI.setLayoutCount = 1; - pipelineLayoutCI.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); - std::array shaderStages = { - loadShader(getShadersPath() + "bufferdeviceaddress/cube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "bufferdeviceaddress/cube.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color }); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareBuffers() - { - // Note that we don't use this buffer for uniforms but rather pass it's address as a reference to the shader, so isntead of the uniform buffer usage we use a different flag - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &scene.buffer, sizeof(glm::mat4))); - VK_CHECK_RESULT(scene.buffer.map()); - - // Get the device of this buffer that is later on passed to the shader (aka "reference") - VkBufferDeviceAddressInfo bufferDeviceAdressInfo{}; - bufferDeviceAdressInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; - bufferDeviceAdressInfo.buffer = scene.buffer.buffer; - scene.bufferDeviceAddress = vkGetBufferDeviceAddressKHR(device, &bufferDeviceAdressInfo); - - for (auto& cube : cubes) { - // Note that we don't use this buffer for uniforms but rather pass it's address as a reference to the shader, so isntead of the uniform buffer usage we use a different flag - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &cube.buffer, sizeof(glm::mat4))); - VK_CHECK_RESULT(cube.buffer.map()); - - // Get the device of this buffer that is later on passed to the shader (aka "reference") - bufferDeviceAdressInfo.buffer = cube.buffer.buffer; - cube.bufferDeviceAddress = vkGetBufferDeviceAddressKHR(device, &bufferDeviceAdressInfo); - } - updateBuffers(); - } - - void updateBuffers() - { - scene.mvp = camera.matrices.perspective * camera.matrices.view; - memcpy(scene.buffer.mapped, &scene, sizeof(glm::mat4)); - - cubes[0].modelMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 0.0f, 0.0f)); - cubes[1].modelMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(1.5f, 0.5f, 0.0f)); - - for (auto& cube : cubes) { - cube.modelMatrix = glm::rotate(cube.modelMatrix, glm::radians(cube.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); - cube.modelMatrix = glm::rotate(cube.modelMatrix, glm::radians(cube.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - cube.modelMatrix = glm::rotate(cube.modelMatrix, glm::radians(cube.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); - cube.modelMatrix = glm::scale(cube.modelMatrix, glm::vec3(0.25f)); - memcpy(cube.buffer.mapped, &cube.modelMatrix, sizeof(glm::mat4)); - } - } - - void prepare() - { - VulkanExampleBase::prepare(); - - // We need this extension function to get the address of a buffer so we can pass it to the shader - vkGetBufferDeviceAddressKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR")); - - loadAssets(); - prepareBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - model.bindBuffers(drawCmdBuffers[i]); - - // Instead of using descriptors to pass global and per-model matrices to the shader, we can now simply pass buffer references via push constants - // The shader then simply reads data from the address of that reference - PushConstantBlock references{}; - // Pass pointer to the global matrix via a buffer device address - references.sceneReference = scene.bufferDeviceAddress; - - for (auto& cube : cubes) { - // Pass pointer to this cube's data buffer via a buffer device address - // So instead of having to bind different descriptors, we only pass a different device address - // This doesn't have to be an address from a different buffer, but could very well be just another address in the same buffer - references.modelReference = cube.bufferDeviceAddress; - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstantBlock), &references); - - model.draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (animate && !paused) { - cubes[0].rotation.x += 2.5f * frameTimer; - if (cubes[0].rotation.x > 360.0f) - cubes[0].rotation.x -= 360.0f; - cubes[1].rotation.y += 2.0f * frameTimer; - if (cubes[1].rotation.x > 360.0f) - cubes[1].rotation.x -= 360.0f; - } - if ((camera.updated) || (animate && !paused)) { - updateBuffers(); - } - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay) - { - if (overlay->header("Settings")) { - overlay->checkBox("Animate", &animate); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/computecloth/computecloth.cpp b/examples/computecloth/computecloth.cpp deleted file mode 100755 index f8b98801..00000000 --- a/examples/computecloth/computecloth.cpp +++ /dev/null @@ -1,768 +0,0 @@ -/* -* Vulkan Example - Compute shader cloth simulation -* -* A compute shader updates a shader storage buffer that contains particles held together by springs and also does basic -* collision detection against a sphere. This storage buffer is then used as the vertex input for the graphics part of the sample -* -* Copyright (C) 2016-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - - -class VulkanExample : public VulkanExampleBase -{ -public: - uint32_t readSet{ 0 }; - uint32_t indexCount{ 0 }; - bool simulateWind{ false }; - // This will be set to true, if the device has a dedicated queue from a compute only queue family - // With such a queue graphics and compute workloads can run in parallel, but this also requires additional barriers (often called "async compute") - // These barriers will release and acquire the resources used in graphics and compute between the different queue families - bool dedicatedComputeQueue{ false }; - - vks::Texture2D textureCloth; - vkglTF::Model modelSphere; - - // The cloth is made from a grid of particles - struct Particle { - glm::vec4 pos; - glm::vec4 vel; - glm::vec4 uv; - glm::vec4 normal; - }; - - // Cloth definition parameters - struct Cloth { - glm::uvec2 gridsize{ 60, 60 }; - glm::vec2 size{ 5.0f, 5.0f }; - } cloth; - - // We put the resource "types" into structs to make this sample easier to understand - - // We use two buffers for our cloth simulation: One with the input cloth data and one for outputting updated values - // The compute pipeline will update the output buffer, and the graphics pipeline will it as a vertex buffer - struct StorageBuffers { - vks::Buffer input; - vks::Buffer output; - } storageBuffers; - - // Resources for the graphics part of the example - struct Graphics { - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - struct Pipelines { - VkPipeline cloth{ VK_NULL_HANDLE }; - VkPipeline sphere{ VK_NULL_HANDLE }; - } pipelines; - // The vertices will be stored in the shader storage buffers, so we only need an index buffer in this structure - vks::Buffer indices; - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - glm::vec4 lightPos{ -2.0f, 4.0f, -2.0f, 1.0f }; - } uniformData; - vks::Buffer uniformBuffer; - } graphics; - - // Resources for the compute part of the example - // Number of compute command buffers: set to 1 for serialized processing or 2 for in-parallel with graphics queue - static constexpr size_t computeCommandBufferCount = 2 ; - struct Compute { - typedef struct Semaphores_t { - VkSemaphore ready{ VK_NULL_HANDLE }; - VkSemaphore complete{ VK_NULL_HANDLE }; - } semaphores_t; - std::array semaphores{}; - VkQueue queue{ VK_NULL_HANDLE }; - VkCommandPool commandPool{ VK_NULL_HANDLE }; - std::array commandBuffers{}; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - std::array descriptorSets{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - struct UniformData { - float deltaT{ 0.0f }; - // These arguments define the spring setup for the cloth piece - // Changing these changes how the cloth reacts - float particleMass{ 0.1f }; - float springStiffness{ 2000.0f }; - float damping{ 0.25f }; - float restDistH{ 0 }; - float restDistV{ 0 }; - float restDistD{ 0 }; - float sphereRadius{ 1.0f }; - glm::vec4 spherePos{ 0.0f, 0.0f, 0.0f, 0.0f }; - glm::vec4 gravity{ 0.0f, 9.8f, 0.0f, 0.0f }; - glm::ivec2 particleCount{ 0 }; - } uniformData; - vks::Buffer uniformBuffer; - } compute; - - VulkanExample() : VulkanExampleBase() - { - title = "Compute shader cloth simulation"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(-30.0f, -45.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -5.0f)); - } - - ~VulkanExample() - { - if (device) { - // Graphics - graphics.indices.destroy(); - graphics.uniformBuffer.destroy(); - vkDestroyPipeline(device, graphics.pipelines.cloth, nullptr); - vkDestroyPipeline(device, graphics.pipelines.sphere, nullptr); - vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, graphics.descriptorSetLayout, nullptr); - textureCloth.destroy(); - - // Compute - compute.uniformBuffer.destroy(); - vkDestroyPipelineLayout(device, compute.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, compute.descriptorSetLayout, nullptr); - vkDestroyPipeline(device, compute.pipeline, nullptr); - for (uint32_t i = 0; i < compute.semaphores.size(); i++) { - vkDestroySemaphore(device, compute.semaphores[i].ready, nullptr); - vkDestroySemaphore(device, compute.semaphores[i].complete, nullptr); - } - vkDestroyCommandPool(device, compute.commandPool, nullptr); - - // SSBOs - storageBuffers.input.destroy(); - storageBuffers.output.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - }; - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - modelSphere.loadFromFile(getAssetPath() + "models/sphere.gltf", vulkanDevice, queue, glTFLoadingFlags); - textureCloth.loadFromFile(getAssetPath() + "textures/vulkan_cloth_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void addGraphicsToComputeBarriers(VkCommandBuffer commandBuffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask) - { - if (dedicatedComputeQueue) { - VkBufferMemoryBarrier bufferBarrier = vks::initializers::bufferMemoryBarrier(); - bufferBarrier.srcAccessMask = srcAccessMask; - bufferBarrier.dstAccessMask = dstAccessMask; - bufferBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - bufferBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - bufferBarrier.size = VK_WHOLE_SIZE; - - std::vector bufferBarriers; - bufferBarrier.buffer = storageBuffers.input.buffer; - bufferBarriers.push_back(bufferBarrier); - bufferBarrier.buffer = storageBuffers.output.buffer; - bufferBarriers.push_back(bufferBarrier); - vkCmdPipelineBarrier(commandBuffer, - srcStageMask, - dstStageMask, - VK_FLAGS_NONE, - 0, nullptr, - static_cast(bufferBarriers.size()), bufferBarriers.data(), - 0, nullptr); - } - } - - void addComputeToComputeBarriers(VkCommandBuffer commandBuffer, uint32_t readSet) - { - VkBufferMemoryBarrier bufferBarrier = vks::initializers::bufferMemoryBarrier(); - bufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - bufferBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bufferBarrier.size = VK_WHOLE_SIZE; - std::vector bufferBarriers; - if (readSet == 0) - { - // SRS - we have written to output.buffer and need a memory barrier before reading it - // - don't need a memory barrier for input.buffer, the execution barrier is enough - bufferBarrier.buffer = storageBuffers.output.buffer; - bufferBarriers.push_back(bufferBarrier); - } - else //if (readSet == 1) - { - // SRS - we have written to input.buffer and need a memory barrier before reading it - // - don't need a memory barrier for output.buffer, the execution barrier is enough - bufferBarrier.buffer = storageBuffers.input.buffer; - bufferBarriers.push_back(bufferBarrier); - } - vkCmdPipelineBarrier( - commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - static_cast(bufferBarriers.size()), bufferBarriers.data(), - 0, nullptr); - } - - void addComputeToGraphicsBarriers(VkCommandBuffer commandBuffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask) - { - if (dedicatedComputeQueue) { - VkBufferMemoryBarrier bufferBarrier = vks::initializers::bufferMemoryBarrier(); - bufferBarrier.srcAccessMask = srcAccessMask; - bufferBarrier.dstAccessMask = dstAccessMask; - bufferBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - bufferBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - bufferBarrier.size = VK_WHOLE_SIZE; - std::vector bufferBarriers; - bufferBarrier.buffer = storageBuffers.input.buffer; - bufferBarriers.push_back(bufferBarrier); - bufferBarrier.buffer = storageBuffers.output.buffer; - bufferBarriers.push_back(bufferBarrier); - vkCmdPipelineBarrier( - commandBuffer, - srcStageMask, - dstStageMask, - VK_FLAGS_NONE, - 0, nullptr, - static_cast(bufferBarriers.size()), bufferBarriers.data(), - 0, nullptr); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Acquire storage buffers from compute queue - addComputeToGraphicsBarriers(drawCmdBuffers[i], 0, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT); - - // Draw the particle system using the update vertex buffer - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - - // Render sphere - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipelines.sphere); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipelineLayout, 0, 1, &graphics.descriptorSet, 0, NULL); - modelSphere.draw(drawCmdBuffers[i]); - - // Render cloth - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipelines.cloth); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipelineLayout, 0, 1, &graphics.descriptorSet, 0, NULL); - vkCmdBindIndexBuffer(drawCmdBuffers[i], graphics.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &storageBuffers.output.buffer, offsets); - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - // release the storage buffers to the compute queue - addGraphicsToComputeBarriers(drawCmdBuffers[i], VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - - } - - void buildComputeCommandBuffer() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - cmdBufInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; - - for (uint32_t i = 0; i < compute.commandBuffers.size(); i++) { - - VK_CHECK_RESULT(vkBeginCommandBuffer(compute.commandBuffers[i], &cmdBufInfo)); - - // Acquire the storage buffers from the graphics queue - addGraphicsToComputeBarriers(compute.commandBuffers[i], 0, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - - vkCmdBindPipeline(compute.commandBuffers[i], VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipeline); - - uint32_t calculateNormals = 0; - vkCmdPushConstants(compute.commandBuffers[i], compute.pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &calculateNormals); - - // Dispatch the compute job - // SRS - Iterations **must** be an even number, so that readSet starts at 1 and the final result ends up in output.buffer with readSet equal to 0 - const uint32_t iterations = 64; - for (uint32_t j = 0; j < iterations; j++) { - readSet = 1 - readSet; - vkCmdBindDescriptorSets(compute.commandBuffers[i], VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineLayout, 0, 1, &compute.descriptorSets[readSet], 0, 0); - - if (j == iterations - 1) { - calculateNormals = 1; - vkCmdPushConstants(compute.commandBuffers[i], compute.pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32_t), &calculateNormals); - } - - vkCmdDispatch(compute.commandBuffers[i], cloth.gridsize.x / 10, cloth.gridsize.y / 10, 1); - - // Don't add a barrier on the last iteration of the loop, since we'll have an explicit release to the graphics queue - if (j != iterations - 1) { - addComputeToComputeBarriers(compute.commandBuffers[i], readSet); - } - - } - - // release the storage buffers back to the graphics queue - addComputeToGraphicsBarriers(compute.commandBuffers[i], VK_ACCESS_SHADER_WRITE_BIT, 0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - vkEndCommandBuffer(compute.commandBuffers[i]); - } - } - - // Setup and fill the shader storage buffers containing the particles - // These buffers are used as shader storage buffers in the compute shader (to update them) and as vertex input in the vertex shader (to display them) - void prepareStorageBuffers() - { - std::vector particleBuffer(cloth.gridsize.x * cloth.gridsize.y); - - float dx = cloth.size.x / (cloth.gridsize.x - 1); - float dy = cloth.size.y / (cloth.gridsize.y - 1); - float du = 1.0f / (cloth.gridsize.x - 1); - float dv = 1.0f / (cloth.gridsize.y - 1); - - // Set up a flat cloth that falls onto sphere - glm::mat4 transM = glm::translate(glm::mat4(1.0f), glm::vec3(-cloth.size.x / 2.0f, -2.0f, -cloth.size.y / 2.0f)); - for (uint32_t i = 0; i < cloth.gridsize.y; i++) { - for (uint32_t j = 0; j < cloth.gridsize.x; j++) { - particleBuffer[i + j * cloth.gridsize.y].pos = transM * glm::vec4(dx * j, 0.0f, dy * i, 1.0f); - particleBuffer[i + j * cloth.gridsize.y].vel = glm::vec4(0.0f); - particleBuffer[i + j * cloth.gridsize.y].uv = glm::vec4(1.0f - du * i, dv * j, 0.0f, 0.0f); - } - } - - VkDeviceSize storageBufferSize = particleBuffer.size() * sizeof(Particle); - - // Staging - // SSBO won't be changed on the host after upload so copy to device local memory - - vks::Buffer stagingBuffer; - - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - storageBufferSize, - particleBuffer.data()); - - // SSBOs will be used both as storage buffers (compute) and vertex buffers (graphics) - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &storageBuffers.input, - storageBufferSize); - - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &storageBuffers.output, - storageBufferSize); - - // Copy from staging buffer - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = {}; - copyRegion.size = storageBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, storageBuffers.output.buffer, 1, ©Region); - // Add an initial release barrier to the graphics queue, - // so that when the compute command buffer executes for the first time - // it doesn't complain about a lack of a corresponding "release" to its "acquire" - addGraphicsToComputeBarriers(copyCmd, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - stagingBuffer.destroy(); - - // Indices - std::vector indices; - for (uint32_t y = 0; y < cloth.gridsize.y - 1; y++) { - for (uint32_t x = 0; x < cloth.gridsize.x; x++) { - indices.push_back((y + 1) * cloth.gridsize.x + x); - indices.push_back((y)*cloth.gridsize.x + x); - } - // Primitive restart (signaled by special value 0xFFFFFFFF) - indices.push_back(0xFFFFFFFF); - } - uint32_t indexBufferSize = static_cast(indices.size()) * sizeof(uint32_t); - indexCount = static_cast(indices.size()); - - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - indexBufferSize, - indices.data()); - - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &graphics.indices, - indexBufferSize); - - // Copy from staging buffer - copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - copyRegion = {}; - copyRegion.size = indexBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, graphics.indices.buffer, 1, ©Region); - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - stagingBuffer.destroy(); - } - - // Prepare the resources used for the graphics part of the sample - void prepareGraphics() - { - // Uniform buffer for passing data to the vertex shader - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &graphics.uniformBuffer, sizeof(Graphics::UniformData)); - VK_CHECK_RESULT(graphics.uniformBuffer.map()); - - // Descriptor pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &graphics.descriptorSetLayout)); - - // Decscriptor set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &graphics.descriptorSet)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(graphics.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &graphics.uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(graphics.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textureCloth.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &graphics.pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, VK_TRUE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - // Rendering pipeline - std::array shaderStages = { - loadShader(getShadersPath() + "computecloth/cloth.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "computecloth/cloth.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(graphics.pipelineLayout, renderPass); - - // Vertex Input - std::vector inputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Particle), VK_VERTEX_INPUT_RATE_VERTEX) - }; - // Attribute descriptions based on the particles of the cloth - std::vector inputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Particle, pos)), - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(Particle, uv)), - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Particle, normal)) - }; - - // Assign to vertex buffer - VkPipelineVertexInputStateCreateInfo inputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - inputState.vertexBindingDescriptionCount = static_cast(inputBindings.size()); - inputState.pVertexBindingDescriptions = inputBindings.data(); - inputState.vertexAttributeDescriptionCount = static_cast(inputAttributes.size()); - inputState.pVertexAttributeDescriptions = inputAttributes.data(); - - pipelineCreateInfo.pVertexInputState = &inputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - pipelineCreateInfo.renderPass = renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &graphics.pipelines.cloth)); - - // Sphere rendering pipeline - pipelineCreateInfo.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Normal }); - inputState.vertexAttributeDescriptionCount = static_cast(inputAttributes.size()); - inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - inputAssemblyState.primitiveRestartEnable = VK_FALSE; - rasterizationState.polygonMode = VK_POLYGON_MODE_FILL; - shaderStages = { - loadShader(getShadersPath() + "computecloth/sphere.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "computecloth/sphere.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &graphics.pipelines.sphere)); - - buildCommandBuffers(); - } - - // Prepare the resources used for the compute part of the sample - void prepareCompute() - { - // Create a compute capable device queue - vkGetDeviceQueue(device, vulkanDevice->queueFamilyIndices.compute, 0, &compute.queue); - - // Uniform buffer for passing data to the compute shader - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &compute.uniformBuffer, sizeof(Compute::UniformData)); - VK_CHECK_RESULT(compute.uniformBuffer.map()); - - // Set some initial values - float dx = cloth.size.x / (cloth.gridsize.x - 1); - float dy = cloth.size.y / (cloth.gridsize.y - 1); - - compute.uniformData.restDistH = dx; - compute.uniformData.restDistV = dy; - compute.uniformData.restDistD = sqrtf(dx * dx + dy * dy); - compute.uniformData.particleCount = cloth.gridsize; - - // Create compute pipeline - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 1), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 2), - }; - - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &compute.descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&compute.descriptorSetLayout, 1); - - // Push constants used to pass some parameters - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_COMPUTE_BIT, sizeof(uint32_t), 0); - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &compute.pipelineLayout)); - - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &compute.descriptorSetLayout, 1); - - // Create two descriptor sets with input and output buffers switched - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &compute.descriptorSets[0])); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &compute.descriptorSets[1])); - - std::vector computeWriteDescriptorSets = { - vks::initializers::writeDescriptorSet(compute.descriptorSets[0], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &storageBuffers.input.descriptor), - vks::initializers::writeDescriptorSet(compute.descriptorSets[0], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, &storageBuffers.output.descriptor), - vks::initializers::writeDescriptorSet(compute.descriptorSets[0], VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &compute.uniformBuffer.descriptor), - - vks::initializers::writeDescriptorSet(compute.descriptorSets[1], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &storageBuffers.output.descriptor), - vks::initializers::writeDescriptorSet(compute.descriptorSets[1], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, &storageBuffers.input.descriptor), - vks::initializers::writeDescriptorSet(compute.descriptorSets[1], VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &compute.uniformBuffer.descriptor) - }; - - vkUpdateDescriptorSets(device, static_cast(computeWriteDescriptorSets.size()), computeWriteDescriptorSets.data(), 0, NULL); - - // Create pipeline - VkComputePipelineCreateInfo computePipelineCreateInfo = vks::initializers::computePipelineCreateInfo(compute.pipelineLayout, 0); - computePipelineCreateInfo.stage = loadShader(getShadersPath() + "computecloth/cloth.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT); - VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &compute.pipeline)); - - // Separate command pool as queue family for compute may be different than graphics - VkCommandPoolCreateInfo cmdPoolInfo = {}; - cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmdPoolInfo.queueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &compute.commandPool)); - - // Create a command buffer for compute operations - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(compute.commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast(compute.commandBuffers.size())); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &compute.commandBuffers[0])); - - // Semaphores for graphics / compute synchronization - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - for (uint32_t i = 0; i < compute.semaphores.size(); i++) { - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphores[i].ready)); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphores[i].complete)); - } - - // Build a single command buffer containing the compute dispatch commands - buildComputeCommandBuffer(); - } - - void updateComputeUBO() - { - if (!paused) { - // SRS - Clamp frameTimer to max 20ms refresh period (e.g. if blocked on resize), otherwise image breakup can occur - compute.uniformData.deltaT = fmin(frameTimer, 0.02f) * 0.0025f; - - if (simulateWind) { - std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::uniform_real_distribution rd(1.0f, 12.0f); - compute.uniformData.gravity.x = cos(glm::radians(-timer * 360.0f)) * (rd(rndEngine) - rd(rndEngine)); - compute.uniformData.gravity.z = sin(glm::radians(timer * 360.0f)) * (rd(rndEngine) - rd(rndEngine)); - } - else { - compute.uniformData.gravity.x = 0.0f; - compute.uniformData.gravity.z = 0.0f; - } - } - else { - compute.uniformData.deltaT = 0.0f; - } - memcpy(compute.uniformBuffer.mapped, &compute.uniformData, sizeof(Compute::UniformData)); - } - - void updateGraphicsUBO() - { - graphics.uniformData.projection = camera.matrices.perspective; - graphics.uniformData.view = camera.matrices.view; - memcpy(graphics.uniformBuffer.mapped, &graphics.uniformData, sizeof(Graphics::UniformData)); - } - - void draw() - { - // As we use both graphics and compute, frame submission is a bit more involved - // We'll be using semaphores to synchronize between the compute shader updating the cloth and the graphics pipeline drawing it - - static bool firstDraw = true; - static uint32_t computeSubmitIndex{ 0 }, graphicsSubmitIndex{ 0 }; - if (computeCommandBufferCount > 1) - { - // SRS - if we are double buffering the compute queue, swap the compute command buffer indices - graphicsSubmitIndex = computeSubmitIndex; - computeSubmitIndex = 1 - graphicsSubmitIndex; - } - - VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); - VkPipelineStageFlags computeWaitDstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - if (!firstDraw) { - computeSubmitInfo.waitSemaphoreCount = 1; - computeSubmitInfo.pWaitSemaphores = &compute.semaphores[computeSubmitIndex].ready; - computeSubmitInfo.pWaitDstStageMask = &computeWaitDstStageMask; - } - else { - firstDraw = false; - if (computeCommandBufferCount > 1) - { - // SRS - if we are double buffering the compute queue, submit extra command buffer at start - computeSubmitInfo.signalSemaphoreCount = 1; - computeSubmitInfo.pSignalSemaphores = &compute.semaphores[graphicsSubmitIndex].complete; - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &compute.commandBuffers[graphicsSubmitIndex]; - - VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); - - // Add an extra set of acquire and release barriers to the graphics queue, - // so that when the second compute command buffer executes for the first time - // it doesn't complain about a lack of a corresponding "acquire" to its "release" and vice versa - VkCommandBuffer barrierCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - addComputeToGraphicsBarriers(barrierCmd, 0, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT); - addGraphicsToComputeBarriers(barrierCmd, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - vulkanDevice->flushCommandBuffer(barrierCmd, queue, true); - } - } - computeSubmitInfo.signalSemaphoreCount = 1; - computeSubmitInfo.pSignalSemaphores = &compute.semaphores[computeSubmitIndex].complete; - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &compute.commandBuffers[computeSubmitIndex]; - - VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); - - // Submit graphics commands - VulkanExampleBase::prepareFrame(); - - VkPipelineStageFlags waitDstStageMask[2] = { - submitPipelineStages, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT - }; - VkSemaphore waitSemaphores[2] = { - semaphores.presentComplete, compute.semaphores[graphicsSubmitIndex].complete - }; - VkSemaphore signalSemaphores[2] = { - semaphores.renderComplete, compute.semaphores[graphicsSubmitIndex].ready - }; - - submitInfo.waitSemaphoreCount = 2; - submitInfo.pWaitDstStageMask = waitDstStageMask; - submitInfo.pWaitSemaphores = waitSemaphores; - submitInfo.signalSemaphoreCount = 2; - submitInfo.pSignalSemaphores = signalSemaphores; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - // Make sure the code works properly both with different queues families for graphics and compute and the same queue family - // You can use DEBUG_FORCE_SHARED_GRAPHICS_COMPUTE_QUEUE preprocessor define to force graphics and compute from the same queue family -#ifdef DEBUG_FORCE_SHARED_GRAPHICS_COMPUTE_QUEUE - vulkanDevice->queueFamilyIndices.compute = vulkanDevice->queueFamilyIndices.graphics; -#endif - // Check whether the compute queue family is distinct from the graphics queue family - dedicatedComputeQueue = vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute; - loadAssets(); - prepareStorageBuffers(); - prepareGraphics(); - prepareCompute(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateGraphicsUBO(); - updateComputeUBO(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay) - { - if (overlay->header("Settings")) { - overlay->checkBox("Simulate wind", &simulateWind); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/computecullandlod/computecullandlod.cpp b/examples/computecullandlod/computecullandlod.cpp deleted file mode 100644 index 82a829e8..00000000 --- a/examples/computecullandlod/computecullandlod.cpp +++ /dev/null @@ -1,822 +0,0 @@ -/* -* Vulkan Example - Compute shader culling and LOD using indirect rendering -* -* Copyright (C) 2016-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -* -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" -#include "frustum.hpp" - - -// Total number of objects (^3) in the scene -#if defined(__ANDROID__) -constexpr auto OBJECT_COUNT = 32; -#else -constexpr auto OBJECT_COUNT = 64; -#endif - -constexpr auto MAX_LOD_LEVEL = 5; - -class VulkanExample : public VulkanExampleBase -{ -public: - bool fixedFrustum = false; - - // The model contains multiple versions of a single object with different levels of detail - vkglTF::Model lodModel; - - // Per-instance data block - struct InstanceData { - glm::vec3 pos{ 0.0f }; - float scale{ 1.0f }; - }; - - // Contains the instanced data - vks::Buffer instanceBuffer; - // Contains the indirect drawing commands - vks::Buffer indirectCommandsBuffer; - vks::Buffer indirectDrawCountBuffer; - - // Indirect draw statistics (updated via compute) - struct { - uint32_t drawCount; // Total number of indirect draw counts to be issued - uint32_t lodCount[MAX_LOD_LEVEL + 1]; // Statistics for number of draws per LOD level (written by compute shader) - } indirectStats; - - // Store the indirect draw commands containing index offsets and instance count per object - std::vector indirectCommands; - - struct { - glm::mat4 projection; - glm::mat4 modelview; - glm::vec4 cameraPos; - glm::vec4 frustumPlanes[6]; - } uboScene; - - struct { - vks::Buffer scene; - } uniformData; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - // Resources for the compute part of the example - struct { - vks::Buffer lodLevelsBuffers; // Contains index start and counts for the different lod levels - VkQueue queue; // Separate queue for compute commands (queue family may differ from the one used for graphics) - VkCommandPool commandPool; // Use a separate command pool (queue family may differ from the one used for graphics) - VkCommandBuffer commandBuffer; // Command buffer storing the dispatch commands and barriers - VkFence fence; // Synchronization fence to avoid rewriting compute CB if still in use - VkSemaphore semaphore; // Used as a wait semaphore for graphics submission - VkDescriptorSetLayout descriptorSetLayout; // Compute shader binding layout - VkDescriptorSet descriptorSet; // Compute shader bindings - VkPipelineLayout pipelineLayout; // Layout of the compute pipeline - VkPipeline pipeline; // Compute pipeline for updating particle positions - } compute{}; - - // View frustum for culling invisible objects - vks::Frustum frustum; - - uint32_t objectCount = 0; - - VulkanExample() : VulkanExampleBase() - { - title = "Compute cull and lod"; - camera.type = Camera::CameraType::firstperson; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setTranslation(glm::vec3(0.5f, 0.0f, 0.0f)); - camera.movementSpeed = 5.0f; - memset(&indirectStats, 0, sizeof(indirectStats)); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - instanceBuffer.destroy(); - indirectCommandsBuffer.destroy(); - uniformData.scene.destroy(); - indirectDrawCountBuffer.destroy(); - compute.lodLevelsBuffers.destroy(); - vkDestroyPipelineLayout(device, compute.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, compute.descriptorSetLayout, nullptr); - vkDestroyPipeline(device, compute.pipeline, nullptr); - vkDestroyFence(device, compute.fence, nullptr); - vkDestroyCommandPool(device, compute.commandPool, nullptr); - vkDestroySemaphore(device, compute.semaphore, nullptr); - } - } - - virtual void getEnabledFeatures() - { - // Enable multi draw indirect if supported - if (deviceFeatures.multiDrawIndirect) { - enabledFeatures.multiDrawIndirect = VK_TRUE; - } - // This is required for for using firstInstance - enabledFeatures.drawIndirectFirstInstance = VK_TRUE; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]{}; - clearValues[0].color = { { 0.18f, 0.27f, 0.5f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Acquire barrier - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - 0, - VK_ACCESS_INDIRECT_COMMAND_READ_BIT, - vulkanDevice->queueFamilyIndices.compute, - vulkanDevice->queueFamilyIndices.graphics, - indirectCommandsBuffer.buffer, - 0, - indirectCommandsBuffer.descriptor.range - }; - - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - // Mesh containing the LODs - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &lodModel.vertices.buffer, offsets); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 1, 1, &instanceBuffer.buffer, offsets); - - vkCmdBindIndexBuffer(drawCmdBuffers[i], lodModel.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - - if (vulkanDevice->features.multiDrawIndirect) - { - vkCmdDrawIndexedIndirect(drawCmdBuffers[i], indirectCommandsBuffer.buffer, 0, static_cast(indirectCommands.size()), sizeof(VkDrawIndexedIndirectCommand)); - } - else - { - // If multi draw is not available, we must issue separate draw commands - for (auto j = 0; j < indirectCommands.size(); j++) - { - vkCmdDrawIndexedIndirect(drawCmdBuffers[i], indirectCommandsBuffer.buffer, j * sizeof(VkDrawIndexedIndirectCommand), 1, sizeof(VkDrawIndexedIndirectCommand)); - } - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - // Release barrier - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_INDIRECT_COMMAND_READ_BIT, - 0, - vulkanDevice->queueFamilyIndices.graphics, - vulkanDevice->queueFamilyIndices.compute, - indirectCommandsBuffer.buffer, - 0, - indirectCommandsBuffer.descriptor.range - }; - - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - lodModel.loadFromFile(getAssetPath() + "models/suzanne_lods.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void buildComputeCommandBuffer() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(compute.commandBuffer, &cmdBufInfo)); - - // Acquire barrier - // Add memory barrier to ensure that the indirect commands have been consumed before the compute shader updates them - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - 0, - VK_ACCESS_SHADER_WRITE_BIT, - vulkanDevice->queueFamilyIndices.graphics, - vulkanDevice->queueFamilyIndices.compute, - indirectCommandsBuffer.buffer, - 0, - indirectCommandsBuffer.descriptor.range - }; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - vkCmdBindPipeline(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipeline); - vkCmdBindDescriptorSets(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineLayout, 0, 1, &compute.descriptorSet, 0, 0); - - // Clear the buffer that the compute shader pass will write statistics and draw calls to - vkCmdFillBuffer(compute.commandBuffer, indirectDrawCountBuffer.buffer, 0, indirectCommandsBuffer.descriptor.range, 0); - - // This barrier ensures that the fill command is finished before the compute shader can start writing to the buffer - VkMemoryBarrier memoryBarrier = vks::initializers::memoryBarrier(); - memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_FLAGS_NONE, - 1, &memoryBarrier, - 0, nullptr, - 0, nullptr); - - // Dispatch the compute job - // The compute shader will do the frustum culling and adjust the indirect draw calls depending on object visibility. - // It also determines the lod to use depending on distance to the viewer. - vkCmdDispatch(compute.commandBuffer, objectCount / 16, 1, 1); - - // Release barrier - // Add memory barrier to ensure that the compute shader has finished writing the indirect command buffer before it's consumed - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_SHADER_WRITE_BIT, - 0, - vulkanDevice->queueFamilyIndices.compute, - vulkanDevice->queueFamilyIndices.graphics, - indirectCommandsBuffer.buffer, - 0, - indirectCommandsBuffer.descriptor.range - }; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - // todo: barrier for indirect stats buffer? - - vkEndCommandBuffer(compute.commandBuffer); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT,0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformData.scene.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // This example uses two different input states, one for the instanced part and one for non-instanced rendering - VkPipelineVertexInputStateCreateInfo inputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - std::vector bindingDescriptions; - std::vector attributeDescriptions; - - // Vertex input bindings - // The instancing pipeline uses a vertex input state with two bindings - bindingDescriptions = { - // Binding point 0: Mesh vertex layout description at per-vertex rate - vks::initializers::vertexInputBindingDescription(0, sizeof(vkglTF::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - // Binding point 1: Instanced data at per-instance rate - vks::initializers::vertexInputBindingDescription(1, sizeof(InstanceData), VK_VERTEX_INPUT_RATE_INSTANCE) - }; - - // Vertex attribute bindings - attributeDescriptions = { - // Per-vertex attributes - // These are advanced for each vertex fetched by the vertex shader - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(vkglTF::Vertex, pos)), // Location 0: Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(vkglTF::Vertex, normal)), // Location 1: Normal - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(vkglTF::Vertex, color)), // Location 2: Texture coordinates - // Per-Instance attributes - // These are fetched for each instance rendered - vks::initializers::vertexInputAttributeDescription(1, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(InstanceData, pos)), // Location 4: Position - vks::initializers::vertexInputAttributeDescription(1, 4, VK_FORMAT_R32_SFLOAT, offsetof(InstanceData, scale)), // Location 5: Scale - }; - inputState.pVertexBindingDescriptions = bindingDescriptions.data(); - inputState.pVertexAttributeDescriptions = attributeDescriptions.data(); - inputState.vertexBindingDescriptionCount = static_cast(bindingDescriptions.size()); - inputState.vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size()); - - // Indirect (and instanced) pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - std::array shaderStages = { - loadShader(getShadersPath() + "computecullandlod/indirectdraw.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "computecullandlod/indirectdraw.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - pipelineCreateInfo.pVertexInputState = &inputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); - } - - void prepareBuffers() - { - objectCount = OBJECT_COUNT * OBJECT_COUNT * OBJECT_COUNT; - - vks::Buffer stagingBuffer; - - std::vector instanceData(objectCount); - indirectCommands.resize(objectCount); - - // Indirect draw commands - for (uint32_t x = 0; x < OBJECT_COUNT; x++) - { - for (uint32_t y = 0; y < OBJECT_COUNT; y++) - { - for (uint32_t z = 0; z < OBJECT_COUNT; z++) - { - uint32_t index = x + y * OBJECT_COUNT + z * OBJECT_COUNT * OBJECT_COUNT; - indirectCommands[index].instanceCount = 1; - indirectCommands[index].firstInstance = index; - // firstIndex and indexCount are written by the compute shader - } - } - } - - indirectStats.drawCount = static_cast(indirectCommands.size()); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - indirectCommands.size() * sizeof(VkDrawIndexedIndirectCommand), - indirectCommands.data())); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &indirectCommandsBuffer, - stagingBuffer.size)); - - vulkanDevice->copyBuffer(&stagingBuffer, &indirectCommandsBuffer, queue); - - stagingBuffer.destroy(); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &indirectDrawCountBuffer, - sizeof(indirectStats))); - - // Map for host access - VK_CHECK_RESULT(indirectDrawCountBuffer.map()); - - // Instance data - for (uint32_t x = 0; x < OBJECT_COUNT; x++) - { - for (uint32_t y = 0; y < OBJECT_COUNT; y++) - { - for (uint32_t z = 0; z < OBJECT_COUNT; z++) - { - uint32_t index = x + y * OBJECT_COUNT + z * OBJECT_COUNT * OBJECT_COUNT; - instanceData[index].pos = glm::vec3((float)x, (float)y, (float)z) - glm::vec3((float)OBJECT_COUNT / 2.0f); - instanceData[index].scale = 2.0f; - } - } - } - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - instanceData.size() * sizeof(InstanceData), - instanceData.data())); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &instanceBuffer, - stagingBuffer.size)); - - // Copy from staging buffer to instance buffer - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = {}; - copyRegion.size = stagingBuffer.size; - vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, instanceBuffer.buffer, 1, ©Region); - // Add an initial release barrier to the graphics queue, - // so that when the compute command buffer executes for the first time - // it doesn't complain about a lack of a corresponding "release" to its "acquire" - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) - { VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_INDIRECT_COMMAND_READ_BIT, - 0, - vulkanDevice->queueFamilyIndices.graphics, - vulkanDevice->queueFamilyIndices.compute, - indirectCommandsBuffer.buffer, - 0, - indirectCommandsBuffer.descriptor.range - }; - - vkCmdPipelineBarrier( - copyCmd, - VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - stagingBuffer.destroy(); - - // Shader storage buffer containing index offsets and counts for the LODs - struct LOD - { - uint32_t firstIndex; - uint32_t indexCount; - float distance; - float _pad0; - }; - std::vector LODLevels; - uint32_t n = 0; - for (auto node : lodModel.nodes) - { - LOD lod{}; - lod.firstIndex = node->mesh->primitives[0]->firstIndex; // First index for this LOD - lod.indexCount = node->mesh->primitives[0]->indexCount; // Index count for this LOD - lod.distance = 5.0f + n * 5.0f; // Starting distance (to viewer) for this LOD - n++; - LODLevels.push_back(lod); - } - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - LODLevels.size() * sizeof(LOD), - LODLevels.data())); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &compute.lodLevelsBuffers, - stagingBuffer.size)); - - vulkanDevice->copyBuffer(&stagingBuffer, &compute.lodLevelsBuffers, queue); - - stagingBuffer.destroy(); - - // Scene uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformData.scene, - sizeof(uboScene))); - - VK_CHECK_RESULT(uniformData.scene.map()); - - updateUniformBuffer(); - } - - void prepareCompute() - { - // Get a compute capable device queue - vkGetDeviceQueue(device, vulkanDevice->queueFamilyIndices.compute, 0, &compute.queue); - - // Create compute pipeline - // Compute pipelines are created separate from graphics pipelines even if they use the same queue (family index) - - std::vector setLayoutBindings = { - // Binding 0: Instance input data buffer - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - VK_SHADER_STAGE_COMPUTE_BIT, - 0), - // Binding 1: Indirect draw command output buffer (input) - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - VK_SHADER_STAGE_COMPUTE_BIT, - 1), - // Binding 2: Uniform buffer with global matrices (input) - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - VK_SHADER_STAGE_COMPUTE_BIT, - 2), - // Binding 3: Indirect draw stats (output) - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - VK_SHADER_STAGE_COMPUTE_BIT, - 3), - // Binding 4: LOD info (input) - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - VK_SHADER_STAGE_COMPUTE_BIT, - 4), - }; - - VkDescriptorSetLayoutCreateInfo descriptorLayout = - vks::initializers::descriptorSetLayoutCreateInfo( - setLayoutBindings.data(), - static_cast(setLayoutBindings.size())); - - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &compute.descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &compute.pipelineLayout)); - - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &compute.descriptorSet)); - - std::vector computeWriteDescriptorSets = - { - // Binding 0: Instance input data buffer - vks::initializers::writeDescriptorSet( - compute.descriptorSet, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - 0, - &instanceBuffer.descriptor), - // Binding 1: Indirect draw command output buffer - vks::initializers::writeDescriptorSet( - compute.descriptorSet, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - 1, - &indirectCommandsBuffer.descriptor), - // Binding 2: Uniform buffer with global matrices - vks::initializers::writeDescriptorSet( - compute.descriptorSet, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - 2, - &uniformData.scene.descriptor), - // Binding 3: Atomic counter (written in shader) - vks::initializers::writeDescriptorSet( - compute.descriptorSet, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - 3, - &indirectDrawCountBuffer.descriptor), - // Binding 4: LOD info - vks::initializers::writeDescriptorSet( - compute.descriptorSet, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - 4, - &compute.lodLevelsBuffers.descriptor) - }; - - vkUpdateDescriptorSets(device, static_cast(computeWriteDescriptorSets.size()), computeWriteDescriptorSets.data(), 0, nullptr); - - // Create pipeline - VkComputePipelineCreateInfo computePipelineCreateInfo = vks::initializers::computePipelineCreateInfo(compute.pipelineLayout, 0); - computePipelineCreateInfo.stage = loadShader(getShadersPath() + "computecullandlod/cull.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT); - - // Use specialization constants to pass max. level of detail (determined by no. of meshes) - VkSpecializationMapEntry specializationEntry{}; - specializationEntry.constantID = 0; - specializationEntry.offset = 0; - specializationEntry.size = sizeof(uint32_t); - - uint32_t specializationData = static_cast(lodModel.nodes.size()) - 1; - - VkSpecializationInfo specializationInfo{}; - specializationInfo.mapEntryCount = 1; - specializationInfo.pMapEntries = &specializationEntry; - specializationInfo.dataSize = sizeof(specializationData); - specializationInfo.pData = &specializationData; - - computePipelineCreateInfo.stage.pSpecializationInfo = &specializationInfo; - - VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &compute.pipeline)); - - // Separate command pool as queue family for compute may be different than graphics - VkCommandPoolCreateInfo cmdPoolInfo = {}; - cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmdPoolInfo.queueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &compute.commandPool)); - - // Create a command buffer for compute operations - VkCommandBufferAllocateInfo cmdBufAllocateInfo = - vks::initializers::commandBufferAllocateInfo( - compute.commandPool, - VK_COMMAND_BUFFER_LEVEL_PRIMARY, - 1); - - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &compute.commandBuffer)); - - // Fence for compute CB sync - VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); - VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &compute.fence)); - - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore)); - - // Build a single command buffer containing the compute dispatch commands - buildComputeCommandBuffer(); - } - - void updateUniformBuffer() - { - uboScene.projection = camera.matrices.perspective; - uboScene.modelview = camera.matrices.view; - if (!fixedFrustum) - { - uboScene.cameraPos = glm::vec4(camera.position, 1.0f) * -1.0f; - frustum.update(uboScene.projection * uboScene.modelview); - memcpy(uboScene.frustumPlanes, frustum.planes.data(), sizeof(glm::vec4) * 6); - } - memcpy(uniformData.scene.mapped, &uboScene, sizeof(uboScene)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareBuffers(); - setupDescriptors(); - preparePipelines(); - prepareCompute(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - - // Submit compute shader for frustum culling - - // Wait for fence to ensure that compute buffer writes have finished - vkWaitForFences(device, 1, &compute.fence, VK_TRUE, UINT64_MAX); - vkResetFences(device, 1, &compute.fence); - - VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; - computeSubmitInfo.signalSemaphoreCount = 1; - computeSubmitInfo.pSignalSemaphores = &compute.semaphore; - - VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); - - // Submit graphics command buffer - - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - - // Wait on present and compute semaphores - std::array stageFlags = { - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - }; - std::array waitSemaphores = { - semaphores.presentComplete, // Wait for presentation to finished - compute.semaphore // Wait for compute to finish - }; - - submitInfo.pWaitSemaphores = waitSemaphores.data(); - submitInfo.waitSemaphoreCount = static_cast(waitSemaphores.size()); - submitInfo.pWaitDstStageMask = stageFlags.data(); - - // Submit to queue - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, compute.fence)); - - VulkanExampleBase::submitFrame(); - - // Get draw count from compute - memcpy(&indirectStats, indirectDrawCountBuffer.mapped, sizeof(indirectStats)); - } - - virtual void render() - { - if (!prepared) - { - return; - } - updateUniformBuffer(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->checkBox("Freeze frustum", &fixedFrustum); - } - if (overlay->header("Statistics")) { - overlay->text("Visible objects: %d", indirectStats.drawCount); - for (uint32_t i = 0; i < MAX_LOD_LEVEL + 1; i++) { - overlay->text("LOD %d: %d", i, indirectStats.lodCount[i]); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/computeheadless/computeheadless.cpp b/examples/computeheadless/computeheadless.cpp deleted file mode 100644 index d0805037..00000000 --- a/examples/computeheadless/computeheadless.cpp +++ /dev/null @@ -1,636 +0,0 @@ -/* -* Vulkan Example - Minimal headless compute example -* -* Copyright (C) 2017-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#if defined(_WIN32) -#pragma comment(linker, "/subsystem:console") -#elif defined(VK_USE_PLATFORM_ANDROID_KHR) -#include -#include -#include -#include -#include "VulkanAndroid.h" -#endif - -#include -#include -#include -#include -#include -#include -#include - -#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) -#define VK_ENABLE_BETA_EXTENSIONS -#endif -#include -#include "VulkanTools.h" -#include "CommandLineParser.hpp" - -#if defined(VK_USE_PLATFORM_ANDROID_KHR) -android_app* androidapp; -#endif - -#define DEBUG (!NDEBUG) - -#define BUFFER_ELEMENTS 32 - -#if defined(VK_USE_PLATFORM_ANDROID_KHR) -#define LOG(...) ((void)__android_log_print(ANDROID_LOG_INFO, "vulkanExample", __VA_ARGS__)) -#else -#define LOG(...) printf(__VA_ARGS__) -#endif - -static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback( - VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, - uint64_t object, - size_t location, - int32_t messageCode, - const char* pLayerPrefix, - const char* pMessage, - void* pUserData) -{ - LOG("[VALIDATION]: %s - %s\n", pLayerPrefix, pMessage); - return VK_FALSE; -} - -CommandLineParser commandLineParser; - -class VulkanExample -{ -public: - VkInstance instance; - VkPhysicalDevice physicalDevice; - VkDevice device; - uint32_t queueFamilyIndex; - VkPipelineCache pipelineCache; - VkQueue queue; - VkCommandPool commandPool; - VkCommandBuffer commandBuffer; - VkFence fence; - VkDescriptorPool descriptorPool; - VkDescriptorSetLayout descriptorSetLayout; - VkDescriptorSet descriptorSet; - VkPipelineLayout pipelineLayout; - VkPipeline pipeline; - VkShaderModule shaderModule; - - VkDebugReportCallbackEXT debugReportCallback{}; - - std::string shaderDir = "glsl"; - - VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkBuffer *buffer, VkDeviceMemory *memory, VkDeviceSize size, void *data = nullptr) - { - // Create the buffer handle - VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(usageFlags, size); - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, buffer)); - - // Create the memory backing up the buffer handle - VkPhysicalDeviceMemoryProperties deviceMemoryProperties; - vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties); - VkMemoryRequirements memReqs; - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - vkGetBufferMemoryRequirements(device, *buffer, &memReqs); - memAlloc.allocationSize = memReqs.size; - // Find a memory type index that fits the properties of the buffer - bool memTypeFound = false; - for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++) { - if ((memReqs.memoryTypeBits & 1) == 1) { - if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & memoryPropertyFlags) == memoryPropertyFlags) { - memAlloc.memoryTypeIndex = i; - memTypeFound = true; - break; - } - } - memReqs.memoryTypeBits >>= 1; - } - assert(memTypeFound); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, memory)); - - if (data != nullptr) { - void *mapped; - VK_CHECK_RESULT(vkMapMemory(device, *memory, 0, size, 0, &mapped)); - memcpy(mapped, data, size); - vkUnmapMemory(device, *memory); - } - - VK_CHECK_RESULT(vkBindBufferMemory(device, *buffer, *memory, 0)); - - return VK_SUCCESS; - } - - VulkanExample() - { - LOG("Running headless compute example\n"); - -#if defined(VK_USE_PLATFORM_ANDROID_KHR) - LOG("loading vulkan lib"); - vks::android::loadVulkanLibrary(); -#endif - - if (commandLineParser.isSet("shaders")) { - shaderDir = commandLineParser.getValueAsString("shaders", "glsl"); - } - - VkApplicationInfo appInfo = {}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "Vulkan headless example"; - appInfo.pEngineName = "VulkanExample"; - appInfo.apiVersion = VK_API_VERSION_1_0; - // Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions - if (shaderDir == "slang") { - appInfo.apiVersion = VK_API_VERSION_1_1; - } - - /* - Vulkan instance creation (without surface extensions) - */ - VkInstanceCreateInfo instanceCreateInfo = {}; - instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - instanceCreateInfo.pApplicationInfo = &appInfo; - - uint32_t layerCount = 1; - const char* validationLayers[] = { "VK_LAYER_KHRONOS_validation" }; - - std::vector instanceExtensions = {}; -#if DEBUG - // Check if layers are available - uint32_t instanceLayerCount; - vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr); - std::vector instanceLayers(instanceLayerCount); - vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayers.data()); - - bool layersAvailable = true; - for (auto layerName : validationLayers) { - bool layerAvailable = false; - for (auto& instanceLayer : instanceLayers) { - if (strcmp(instanceLayer.layerName, layerName) == 0) { - layerAvailable = true; - break; - } - } - if (!layerAvailable) { - layersAvailable = false; - break; - } - } - - if (layersAvailable) { - instanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); - instanceCreateInfo.ppEnabledLayerNames = validationLayers; - instanceCreateInfo.enabledLayerCount = layerCount; - } -#endif -#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) - // SRS - When running on macOS with MoltenVK, enable VK_KHR_get_physical_device_properties2 (required by VK_KHR_portability_subset) - instanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); -#if defined(VK_KHR_portability_enumeration) - // SRS - When running on macOS with MoltenVK and VK_KHR_portability_enumeration is defined and supported by the instance, enable the extension and the flag - uint32_t instanceExtCount = 0; - vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, nullptr); - if (instanceExtCount > 0) - { - std::vector extensions(instanceExtCount); - if (vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, &extensions.front()) == VK_SUCCESS) - { - for (VkExtensionProperties extension : extensions) - { - if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) - { - instanceExtensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); - instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; - break; - } - } - } - } -#endif -#endif - instanceCreateInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size(); - instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data(); - VK_CHECK_RESULT(vkCreateInstance(&instanceCreateInfo, nullptr, &instance)); - -#if defined(VK_USE_PLATFORM_ANDROID_KHR) - vks::android::loadVulkanFunctions(instance); -#endif -#if DEBUG - if (layersAvailable) { - VkDebugReportCallbackCreateInfoEXT debugReportCreateInfo = {}; - debugReportCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; - debugReportCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; - debugReportCreateInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)debugMessageCallback; - - // We have to explicitly load this function. - PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT")); - assert(vkCreateDebugReportCallbackEXT); - VK_CHECK_RESULT(vkCreateDebugReportCallbackEXT(instance, &debugReportCreateInfo, nullptr, &debugReportCallback)); - } -#endif - - /* - Vulkan device creation - */ - // Physical device (always use first) - uint32_t deviceCount = 0; - VK_CHECK_RESULT(vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr)); - std::vector physicalDevices(deviceCount); - VK_CHECK_RESULT(vkEnumeratePhysicalDevices(instance, &deviceCount, physicalDevices.data())); - physicalDevice = physicalDevices[0]; - - VkPhysicalDeviceProperties deviceProperties; - vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); - LOG("GPU: %s\n", deviceProperties.deviceName); - - // Request a single compute queue - const float defaultQueuePriority(0.0f); - VkDeviceQueueCreateInfo queueCreateInfo = {}; - uint32_t queueFamilyCount; - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr); - std::vector queueFamilyProperties(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilyProperties.data()); - for (uint32_t i = 0; i < static_cast(queueFamilyProperties.size()); i++) { - if (queueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) { - queueFamilyIndex = i; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = i; - queueCreateInfo.queueCount = 1; - queueCreateInfo.pQueuePriorities = &defaultQueuePriority; - break; - } - } - // Create logical device - VkDeviceCreateInfo deviceCreateInfo = {}; - deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - deviceCreateInfo.queueCreateInfoCount = 1; - deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; - std::vector deviceExtensions = {}; - - // Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions - if (shaderDir == "slang") { - deviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); - deviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); - } - -#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_KHR_portability_subset) - // When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension - uint32_t deviceExtCount = 0; - vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, nullptr); - if (deviceExtCount > 0) - { - std::vector extensions(deviceExtCount); - if (vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, &extensions.front()) == VK_SUCCESS) - { - for (VkExtensionProperties extension : extensions) - { - if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) - { - deviceExtensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); - break; - } - } - } - } -#endif - deviceCreateInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size(); - deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data(); - VK_CHECK_RESULT(vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device)); - - // Get a compute queue - vkGetDeviceQueue(device, queueFamilyIndex, 0, &queue); - - // Compute command pool - VkCommandPoolCreateInfo cmdPoolInfo = {}; - cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmdPoolInfo.queueFamilyIndex = queueFamilyIndex; - cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &commandPool)); - - /* - Prepare storage buffers - */ - std::vector computeInput(BUFFER_ELEMENTS); - std::vector computeOutput(BUFFER_ELEMENTS); - - // Fill input data - uint32_t n = 0; - std::generate(computeInput.begin(), computeInput.end(), [&n] { return n++; }); - - const VkDeviceSize bufferSize = BUFFER_ELEMENTS * sizeof(uint32_t); - - VkBuffer deviceBuffer, hostBuffer; - VkDeviceMemory deviceMemory, hostMemory; - - // Copy input data to VRAM using a staging buffer - { - createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - &hostBuffer, - &hostMemory, - bufferSize, - computeInput.data()); - - // Flush writes to host visible buffer - void* mapped; - vkMapMemory(device, hostMemory, 0, VK_WHOLE_SIZE, 0, &mapped); - VkMappedMemoryRange mappedRange = vks::initializers::mappedMemoryRange(); - mappedRange.memory = hostMemory; - mappedRange.offset = 0; - mappedRange.size = VK_WHOLE_SIZE; - vkFlushMappedMemoryRanges(device, 1, &mappedRange); - vkUnmapMemory(device, hostMemory); - - createBuffer( - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &deviceBuffer, - &deviceMemory, - bufferSize); - - // Copy to staging buffer - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - VkCommandBuffer copyCmd; - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, ©Cmd)); - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo)); - - VkBufferCopy copyRegion = {}; - copyRegion.size = bufferSize; - vkCmdCopyBuffer(copyCmd, hostBuffer, deviceBuffer, 1, ©Region); - VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd)); - - VkSubmitInfo submitInfo = vks::initializers::submitInfo(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = ©Cmd; - VkFenceCreateInfo fenceInfo = vks::initializers::fenceCreateInfo(VK_FLAGS_NONE); - VkFence fence; - VK_CHECK_RESULT(vkCreateFence(device, &fenceInfo, nullptr, &fence)); - - // Submit to the queue - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence)); - VK_CHECK_RESULT(vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX)); - - vkDestroyFence(device, fence, nullptr); - vkFreeCommandBuffers(device, commandPool, 1, ©Cmd); - } - - /* - Prepare compute pipeline - */ - { - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1), - }; - - VkDescriptorPoolCreateInfo descriptorPoolInfo = - vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = - vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = - vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - VkDescriptorSetAllocateInfo allocInfo = - vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - VkDescriptorBufferInfo bufferDescriptor = { deviceBuffer, 0, VK_WHOLE_SIZE }; - std::vector computeWriteDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &bufferDescriptor), - }; - vkUpdateDescriptorSets(device, static_cast(computeWriteDescriptorSets.size()), computeWriteDescriptorSets.data(), 0, NULL); - - VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {}; - pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - VK_CHECK_RESULT(vkCreatePipelineCache(device, &pipelineCacheCreateInfo, nullptr, &pipelineCache)); - - // Create pipeline - VkComputePipelineCreateInfo computePipelineCreateInfo = vks::initializers::computePipelineCreateInfo(pipelineLayout, 0); - - // Pass SSBO size via specialization constant - struct SpecializationData { - uint32_t BUFFER_ELEMENT_COUNT = BUFFER_ELEMENTS; - } specializationData; - VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t)); - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(SpecializationData), &specializationData); - - const std::string shadersPath = getShaderBasePath() + shaderDir + "/computeheadless/"; - - VkPipelineShaderStageCreateInfo shaderStage = {}; - shaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStage.stage = VK_SHADER_STAGE_COMPUTE_BIT; -#if defined(VK_USE_PLATFORM_ANDROID_KHR) - shaderStage.module = vks::tools::loadShader(androidapp->activity->assetManager, (shadersPath + "headless.comp.spv").c_str(), device); -#else - shaderStage.module = vks::tools::loadShader((shadersPath + "headless.comp.spv").c_str(), device); -#endif - shaderStage.pName = "main"; - shaderStage.pSpecializationInfo = &specializationInfo; - shaderModule = shaderStage.module; - - assert(shaderStage.module != VK_NULL_HANDLE); - computePipelineCreateInfo.stage = shaderStage; - VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &pipeline)); - - // Create a command buffer for compute operations - VkCommandBufferAllocateInfo cmdBufAllocateInfo = - vks::initializers::commandBufferAllocateInfo(commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &commandBuffer)); - - // Fence for compute CB sync - VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); - VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); - } - - /* - Command buffer creation (for compute work submission) - */ - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &cmdBufInfo)); - - // Barrier to ensure that input buffer transfer is finished before compute shader reads from it - VkBufferMemoryBarrier bufferBarrier = vks::initializers::bufferMemoryBarrier(); - bufferBarrier.buffer = deviceBuffer; - bufferBarrier.size = VK_WHOLE_SIZE; - bufferBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - bufferBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - - vkCmdPipelineBarrier( - commandBuffer, - VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 1, &bufferBarrier, - 0, nullptr); - - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 1, &descriptorSet, 0, 0); - - vkCmdDispatch(commandBuffer, BUFFER_ELEMENTS, 1, 1); - - // Barrier to ensure that shader writes are finished before buffer is read back from GPU - bufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - bufferBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - bufferBarrier.buffer = deviceBuffer; - bufferBarrier.size = VK_WHOLE_SIZE; - bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - - vkCmdPipelineBarrier( - commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 1, &bufferBarrier, - 0, nullptr); - - // Read back to host visible buffer - VkBufferCopy copyRegion = {}; - copyRegion.size = bufferSize; - vkCmdCopyBuffer(commandBuffer, deviceBuffer, hostBuffer, 1, ©Region); - - // Barrier to ensure that buffer copy is finished before host reading from it - bufferBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - bufferBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT; - bufferBarrier.buffer = hostBuffer; - bufferBarrier.size = VK_WHOLE_SIZE; - bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - - vkCmdPipelineBarrier( - commandBuffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_HOST_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 1, &bufferBarrier, - 0, nullptr); - - VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer)); - - // Submit compute work - vkResetFences(device, 1, &fence); - const VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; - VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); - computeSubmitInfo.pWaitDstStageMask = &waitStageMask; - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &commandBuffer; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &computeSubmitInfo, fence)); - VK_CHECK_RESULT(vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX)); - - // Make device writes visible to the host - void *mapped; - vkMapMemory(device, hostMemory, 0, VK_WHOLE_SIZE, 0, &mapped); - VkMappedMemoryRange mappedRange = vks::initializers::mappedMemoryRange(); - mappedRange.memory = hostMemory; - mappedRange.offset = 0; - mappedRange.size = VK_WHOLE_SIZE; - vkInvalidateMappedMemoryRanges(device, 1, &mappedRange); - - // Copy to output - memcpy(computeOutput.data(), mapped, bufferSize); - vkUnmapMemory(device, hostMemory); - } - - vkQueueWaitIdle(queue); - - // Output buffer contents - LOG("Compute input:\n"); - for (auto v : computeInput) { - LOG("%d \t", v); - } - std::cout << std::endl; - - LOG("Compute output:\n"); - for (auto v : computeOutput) { - LOG("%d \t", v); - } - std::cout << std::endl; - - // Clean up - vkDestroyBuffer(device, deviceBuffer, nullptr); - vkFreeMemory(device, deviceMemory, nullptr); - vkDestroyBuffer(device, hostBuffer, nullptr); - vkFreeMemory(device, hostMemory, nullptr); - } - - ~VulkanExample() - { - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyDescriptorPool(device, descriptorPool, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineCache(device, pipelineCache, nullptr); - vkDestroyFence(device, fence, nullptr); - vkDestroyCommandPool(device, commandPool, nullptr); - vkDestroyShaderModule(device, shaderModule, nullptr); - vkDestroyDevice(device, nullptr); -#if DEBUG - if (debugReportCallback) { - PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallback = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT")); - assert(vkDestroyDebugReportCallback); - vkDestroyDebugReportCallback(instance, debugReportCallback, nullptr); - } -#endif - vkDestroyInstance(instance, nullptr); - } -}; - -#if defined(VK_USE_PLATFORM_ANDROID_KHR) -void handleAppCommand(android_app * app, int32_t cmd) { - if (cmd == APP_CMD_INIT_WINDOW) { - VulkanExample *vulkanExample = new VulkanExample(); - delete(vulkanExample); - ANativeActivity_finish(app->activity); - } -} -void android_main(android_app* state) { - androidapp = state; - androidapp->onAppCmd = handleAppCommand; - int ident, events; - struct android_poll_source* source; - while ((ident = ALooper_pollOnce(-1, NULL, &events, (void**)&source)) > ALOOPER_POLL_TIMEOUT) { - if (source != NULL) { - source->process(androidapp, source); - } - if (androidapp->destroyRequested != 0) { - break; - } - } -} -#else -int main(int argc, char* argv[]) { - commandLineParser.add("help", { "--help" }, 0, "Show help"); - commandLineParser.add("shaders", { "-s", "--shaders" }, 1, "Select shader type to use (glsl, hlsl or slang)"); - commandLineParser.parse(argc, argv); - if (commandLineParser.isSet("help")) { - commandLineParser.printHelp(); - std::cin.get(); - return 0; - } - VulkanExample *vulkanExample = new VulkanExample(); - std::cout << "Finished. Press enter to terminate..."; - std::cin.get(); - delete(vulkanExample); - return 0; -} -#endif diff --git a/examples/computenbody/computenbody.cpp b/examples/computenbody/computenbody.cpp deleted file mode 100644 index dba6934b..00000000 --- a/examples/computenbody/computenbody.cpp +++ /dev/null @@ -1,677 +0,0 @@ -/* -* Vulkan Example - Compute shader N-body simulation using two passes and shared compute shader memory -* -* This sample shows how to combine compute and graphics for doing N-body particle simulaton -* It calculates the particle system movement using two separate compute passes: calculating particle positions and integrating particles -* For that a shader storage buffer is used which is then used as a vertex buffer for drawing the particle system with a graphics pipeline -* To optimize performance, the compute shaders use shared memory -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -#if defined(__ANDROID__) -// Lower particle count on Android for performance reasons -#define PARTICLES_PER_ATTRACTOR 3 * 1024 -#else -#define PARTICLES_PER_ATTRACTOR 4 * 1024 -#endif - -class VulkanExample : public VulkanExampleBase -{ -public: - struct Textures { - vks::Texture2D particle; - vks::Texture2D gradient; - } textures{}; - - // Particle Definition - struct Particle { - glm::vec4 pos; // xyz = position, w = mass - glm::vec4 vel; // xyz = velocity, w = gradient texture position - }; - uint32_t numParticles{ 0 }; - - // We use a shader storage buffer object to store the particlces - // This is updated by the compute pipeline and displayed as a vertex buffer by the graphics pipeline - vks::Buffer storageBuffer; - - // Resources for the graphics part of the example - struct Graphics { - uint32_t queueFamilyIndex; // Used to check if compute and graphics queue families differ and require additional barriers - VkDescriptorSetLayout descriptorSetLayout; // Particle system rendering shader binding layout - VkDescriptorSet descriptorSet; // Particle system rendering shader bindings - VkPipelineLayout pipelineLayout; // Layout of the graphics pipeline - VkPipeline pipeline; // Particle rendering pipeline - VkSemaphore semaphore; // Execution dependency between compute & graphic submission - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - glm::vec2 screenDim; - } uniformData; - vks::Buffer uniformBuffer; // Contains scene matrices - } graphics; - - // Resources for the compute part of the example - struct Compute { - uint32_t queueFamilyIndex; // Used to check if compute and graphics queue families differ and require additional barriers - VkQueue queue; // Separate queue for compute commands (queue family may differ from the one used for graphics) - VkCommandPool commandPool; // Use a separate command pool (queue family may differ from the one used for graphics) - VkCommandBuffer commandBuffer; // Command buffer storing the dispatch commands and barriers - VkSemaphore semaphore; // Execution dependency between compute & graphic submission - VkDescriptorSetLayout descriptorSetLayout; // Compute shader binding layout - VkDescriptorSet descriptorSet; // Compute shader bindings - VkPipelineLayout pipelineLayout; // Layout of the compute pipeline - VkPipeline pipelineCalculate; // Compute pipeline for N-Body velocity calculation (1st pass) - VkPipeline pipelineIntegrate; // Compute pipeline for euler integration (2nd pass) - struct UniformData { // Compute shader uniform block object - float deltaT{ 0.0f }; // Frame delta time - int32_t particleCount{ 0 }; - // Parameters used to control the behaviour of the particle system - float gravity{ 0.002f }; - float power{ 0.75f }; - float soften{ 0.05f }; - } uniformData; - vks::Buffer uniformBuffer; // Uniform buffer object containing particle system parameters - } compute; - - VulkanExample() : VulkanExampleBase() - { - title = "Compute shader N-body system"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(-26.0f, 75.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -14.0f)); - camera.movementSpeed = 2.5f; - } - - ~VulkanExample() - { - if (device) { - // Graphics - graphics.uniformBuffer.destroy(); - vkDestroyPipeline(device, graphics.pipeline, nullptr); - vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, graphics.descriptorSetLayout, nullptr); - vkDestroySemaphore(device, graphics.semaphore, nullptr); - - // Compute - compute.uniformBuffer.destroy(); - vkDestroyPipelineLayout(device, compute.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, compute.descriptorSetLayout, nullptr); - vkDestroyPipeline(device, compute.pipelineCalculate, nullptr); - vkDestroyPipeline(device, compute.pipelineIntegrate, nullptr); - vkDestroySemaphore(device, compute.semaphore, nullptr); - vkDestroyCommandPool(device, compute.commandPool, nullptr); - - storageBuffer.destroy(); - - textures.particle.destroy(); - textures.gradient.destroy(); - } - } - - void loadAssets() - { - textures.particle.loadFromFile(getAssetPath() + "textures/particle01_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.gradient.loadFromFile(getAssetPath() + "textures/particle_gradient_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { {0.0f, 0.0f, 0.0f, 1.0f} }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Acquire barrier - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - 0, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - compute.queueFamilyIndex, - graphics.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - // Draw the particle system using the update vertex buffer - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipelineLayout, 0, 1, &graphics.descriptorSet, 0, nullptr); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &storageBuffer.buffer, offsets); - vkCmdDraw(drawCmdBuffers[i], numParticles, 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - // Release barrier - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - 0, - graphics.queueFamilyIndex, - compute.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - - } - - void buildComputeCommandBuffer() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(compute.commandBuffer, &cmdBufInfo)); - - // Acquire barrier - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - 0, - VK_ACCESS_SHADER_WRITE_BIT, - graphics.queueFamilyIndex, - compute.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - // First pass: Calculate particle movement - // ------------------------------------------------------------------------------------------------------- - vkCmdBindPipeline(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineCalculate); - vkCmdBindDescriptorSets(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineLayout, 0, 1, &compute.descriptorSet, 0, 0); - vkCmdDispatch(compute.commandBuffer, numParticles / 256, 1, 1); - - // Add memory barrier to ensure that the computer shader has finished writing to the buffer - VkBufferMemoryBarrier bufferBarrier = vks::initializers::bufferMemoryBarrier(); - bufferBarrier.buffer = storageBuffer.buffer; - bufferBarrier.size = storageBuffer.descriptor.range; - bufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - bufferBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - // Transfer ownership if compute and graphics queue family indices differ - bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 1, &bufferBarrier, - 0, nullptr); - - // Second pass: Integrate particles - // ------------------------------------------------------------------------------------------------------- - vkCmdBindPipeline(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineIntegrate); - vkCmdDispatch(compute.commandBuffer, numParticles / 256, 1, 1); - - // Release barrier - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_SHADER_WRITE_BIT, - 0, - compute.queueFamilyIndex, - graphics.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - vkEndCommandBuffer(compute.commandBuffer); - } - - // Setup and fill the compute shader storage buffers containing the particles - void prepareStorageBuffers() - { - // We mark a few particles as attractors that move along a given path, these will pull in the other particles - std::vector attractors = { - glm::vec3(5.0f, 0.0f, 0.0f), - glm::vec3(-5.0f, 0.0f, 0.0f), - glm::vec3(0.0f, 0.0f, 5.0f), - glm::vec3(0.0f, 0.0f, -5.0f), - glm::vec3(0.0f, 4.0f, 0.0f), - glm::vec3(0.0f, -8.0f, 0.0f), - }; - - numParticles = static_cast(attractors.size()) * PARTICLES_PER_ATTRACTOR; - - // Initial particle positions - std::vector particleBuffer(numParticles); - - std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::normal_distribution rndDist(0.0f, 1.0f); - - for (uint32_t i = 0; i < static_cast(attractors.size()); i++) - { - for (uint32_t j = 0; j < PARTICLES_PER_ATTRACTOR; j++) - { - Particle& particle = particleBuffer[i * PARTICLES_PER_ATTRACTOR + j]; - - // First particle in group as heavy center of gravity - if (j == 0) - { - particle.pos = glm::vec4(attractors[i] * 1.5f, 90000.0f); - particle.vel = glm::vec4(glm::vec4(0.0f)); - } - else - { - // Position - glm::vec3 position(attractors[i] + glm::vec3(rndDist(rndEngine), rndDist(rndEngine), rndDist(rndEngine)) * 0.75f); - float len = glm::length(glm::normalize(position - attractors[i])); - position.y *= 2.0f - (len * len); - - // Velocity - glm::vec3 angular = glm::vec3(0.5f, 1.5f, 0.5f) * (((i % 2) == 0) ? 1.0f : -1.0f); - glm::vec3 velocity = glm::cross((position - attractors[i]), angular) + glm::vec3(rndDist(rndEngine), rndDist(rndEngine), rndDist(rndEngine) * 0.025f); - - float mass = (rndDist(rndEngine) * 0.5f + 0.5f) * 75.0f; - particle.pos = glm::vec4(position, mass); - particle.vel = glm::vec4(velocity, 0.0f); - } - - // Color gradient offset - particle.vel.w = (float)i * 1.0f / static_cast(attractors.size()); - } - } - - compute.uniformData.particleCount = numParticles; - - VkDeviceSize storageBufferSize = particleBuffer.size() * sizeof(Particle); - - // Staging - // SSBO won't be changed on the host after upload so copy to device local memory - - vks::Buffer stagingBuffer; - - vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer, storageBufferSize, particleBuffer.data()); - // The SSBO will be used as a storage buffer for the compute pipeline and as a vertex buffer in the graphics pipeline - vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &storageBuffer, storageBufferSize); - - // Copy from staging buffer to storage buffer - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = {}; - copyRegion.size = storageBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, storageBuffer.buffer, 1, ©Region); - // Execute a transfer barrier to the compute queue, if necessary - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - 0, - graphics.queueFamilyIndex, - compute.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - copyCmd, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - stagingBuffer.destroy(); - } - - void prepareGraphics() - { - // Vertex shader uniform buffer block - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &graphics.uniformBuffer, sizeof(Graphics::UniformData)); - VK_CHECK_RESULT(graphics.uniformBuffer.map()); - - // Descriptor pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor layout - std::vector setLayoutBindings; - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 2), - }; - - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &graphics.descriptorSetLayout)); - - // Descriptor set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &graphics.descriptorSet)); - - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(graphics.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &textures.particle.descriptor), - vks::initializers::writeDescriptorSet(graphics.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.gradient.descriptor), - vks::initializers::writeDescriptorSet(graphics.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &graphics.uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Pipeline layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &graphics.pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_ALWAYS); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Vertex Input state - std::vector inputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Particle), VK_VERTEX_INPUT_RATE_VERTEX) - }; - std::vector inputAttributes = { - // Location 0 : Position - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Particle, pos)), - // Location 1 : Velocity (used for color gradient lookup) - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Particle, vel)), - }; - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(inputBindings.size()); - vertexInputState.pVertexBindingDescriptions = inputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(inputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = inputAttributes.data(); - - // Shaders - shaderStages[0] = loadShader(getShadersPath() + "computenbody/particle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "computenbody/particle.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(graphics.pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &vertexInputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - pipelineCreateInfo.renderPass = renderPass; - - // Additive blending - blendAttachmentState.colorWriteMask = 0xF; - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &graphics.pipeline)); - - // We use a semaphore to synchronize compute and graphics - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &graphics.semaphore)); - - // Signal the semaphore for the first run - VkSubmitInfo submitInfo = vks::initializers::submitInfo(); - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = &graphics.semaphore; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VK_CHECK_RESULT(vkQueueWaitIdle(queue)); - - buildCommandBuffers(); - } - - void prepareCompute() - { - // Create a compute capable device queue - // The VulkanDevice::createLogicalDevice functions finds a compute capable queue and prefers queue families that only support compute - // Depending on the implementation this may result in different queue family indices for graphics and computes, - // requiring proper synchronization (see the memory barriers in buildComputeCommandBuffer) - vkGetDeviceQueue(device, compute.queueFamilyIndex, 0, &compute.queue); - - // Compute shader uniform buffer block - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &compute.uniformBuffer, sizeof(Compute::UniformData)); - VK_CHECK_RESULT(compute.uniformBuffer.map()); - - // Create compute pipeline - // Compute pipelines are created separate from graphics pipelines even if they use the same queue (family index) - - std::vector setLayoutBindings = { - // Binding 0 : Particle position storage buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 0), - // Binding 1 : Uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 1), - }; - - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &compute.descriptorSetLayout)); - - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &compute.descriptorSet)); - - std::vector computeWriteDescriptorSets = { - // Binding 0 : Particle position storage buffer - vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &storageBuffer.descriptor), - // Binding 1 : Uniform buffer - vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,1,&compute.uniformBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(computeWriteDescriptorSets.size()), computeWriteDescriptorSets.data(), 0, nullptr); - - // Create pipelines - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &compute.pipelineLayout)); - - VkComputePipelineCreateInfo computePipelineCreateInfo = vks::initializers::computePipelineCreateInfo(compute.pipelineLayout, 0); - - // 1st pass - computePipelineCreateInfo.stage = loadShader(getShadersPath() + "computenbody/particle_calculate.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT); - - // We want to use as much shared memory for the compute shader invocations as available, so we calculate it based on the device limits and pass it to the shader via specialization constants - uint32_t sharedDataSize = std::min((uint32_t)1024, (uint32_t)(vulkanDevice->properties.limits.maxComputeSharedMemorySize / sizeof(glm::vec4))); - VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t)); - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(int32_t), &sharedDataSize); - computePipelineCreateInfo.stage.pSpecializationInfo = &specializationInfo; - - VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &compute.pipelineCalculate)); - - // 2nd pass - computePipelineCreateInfo.stage = loadShader(getShadersPath() + "computenbody/particle_integrate.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT); - VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &compute.pipelineIntegrate)); - - // Separate command pool as queue family for compute may be different than graphics - VkCommandPoolCreateInfo cmdPoolInfo = {}; - cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmdPoolInfo.queueFamilyIndex = compute.queueFamilyIndex; - cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &compute.commandPool)); - - // Create a command buffer for compute operations - compute.commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, compute.commandPool); - - // Semaphore for compute & graphics sync - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore)); - - // Build a single command buffer containing the compute dispatch commands - buildComputeCommandBuffer(); - } - - void updateComputeUniformBuffers() - { - compute.uniformData.deltaT = paused ? 0.0f : frameTimer * 0.05f; - memcpy(compute.uniformBuffer.mapped, &compute.uniformData, sizeof(Compute::UniformData)); - } - - void updateGraphicsUniformBuffers() - { - graphics.uniformData.projection = camera.matrices.perspective; - graphics.uniformData.view = camera.matrices.view; - graphics.uniformData.screenDim = glm::vec2((float)width, (float)height); - memcpy(graphics.uniformBuffer.mapped, &graphics.uniformData, sizeof(Graphics::UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - // We will be using the queue family indices to check if graphics and compute queue families differ - // If that's the case, we need additional barriers for acquiring and releasing resources - graphics.queueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - compute.queueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - loadAssets(); - prepareStorageBuffers(); - prepareGraphics(); - prepareCompute(); - prepared = true; - } - - void draw() - { - // Wait for rendering finished - VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - - // Submit compute commands - VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; - computeSubmitInfo.waitSemaphoreCount = 1; - computeSubmitInfo.pWaitSemaphores = &graphics.semaphore; - computeSubmitInfo.pWaitDstStageMask = &waitStageMask; - computeSubmitInfo.signalSemaphoreCount = 1; - computeSubmitInfo.pSignalSemaphores = &compute.semaphore; - VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::prepareFrame(); - - VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - VkSemaphore graphicsWaitSemaphores[] = { compute.semaphore, semaphores.presentComplete }; - VkSemaphore graphicsSignalSemaphores[] = { graphics.semaphore, semaphores.renderComplete }; - - // Submit graphics commands - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - submitInfo.waitSemaphoreCount = 2; - submitInfo.pWaitSemaphores = graphicsWaitSemaphores; - submitInfo.pWaitDstStageMask = graphicsWaitStageMasks; - submitInfo.signalSemaphoreCount = 2; - submitInfo.pSignalSemaphores = graphicsSignalSemaphores; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateComputeUniformBuffers(); - updateGraphicsUniformBuffers(); - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/computeparticles/computeparticles.cpp b/examples/computeparticles/computeparticles.cpp deleted file mode 100644 index 2d97b987..00000000 --- a/examples/computeparticles/computeparticles.cpp +++ /dev/null @@ -1,646 +0,0 @@ -/* -* Vulkan Example - Attraction based compute shader particle system -* -* Updated compute shader by Lukas Bergdoll (https://github.com/Voultapher) -* -* Copyright (C) 2016-2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -#if defined(__ANDROID__) -// Lower particle count on Android for performance reasons -#define PARTICLE_COUNT 128 * 1024 -#else -#define PARTICLE_COUNT 256 * 1024 -#endif - -class VulkanExample : public VulkanExampleBase -{ -public: - float timer = 0.0f; - float animStart = 20.0f; - bool attachToCursor = false; - - struct { - vks::Texture2D particle; - vks::Texture2D gradient; - } textures; - - // SSBO particle declaration - struct Particle { - glm::vec2 pos; // Particle position - glm::vec2 vel; // Particle velocity - glm::vec4 gradientPos; // Texture coordinates for the gradient ramp map - }; - - // We use a shader storage buffer object to store the particlces - // This is updated by the compute pipeline and displayed as a vertex buffer by the graphics pipeline - vks::Buffer storageBuffer; - - // Resources for the graphics part of the example - struct Graphics { - uint32_t queueFamilyIndex; // Used to check if compute and graphics queue families differ and require additional barriers - VkDescriptorSetLayout descriptorSetLayout; // Particle system rendering shader binding layout - VkDescriptorSet descriptorSet; // Particle system rendering shader bindings - VkPipelineLayout pipelineLayout; // Layout of the graphics pipeline - VkPipeline pipeline; // Particle rendering pipeline - VkSemaphore semaphore; // Execution dependency between compute & graphic submission - } graphics; - - // Resources for the compute part of the example - struct Compute { - uint32_t queueFamilyIndex; // Used to check if compute and graphics queue families differ and require additional barriers - VkQueue queue; // Separate queue for compute commands (queue family may differ from the one used for graphics) - VkCommandPool commandPool; // Use a separate command pool (queue family may differ from the one used for graphics) - VkCommandBuffer commandBuffer; // Command buffer storing the dispatch commands and barriers - VkSemaphore semaphore; // Execution dependency between compute & graphic submission - VkDescriptorSetLayout descriptorSetLayout; // Compute shader binding layout - VkDescriptorSet descriptorSet; // Compute shader bindings - VkPipelineLayout pipelineLayout; // Layout of the compute pipeline - VkPipeline pipeline; // Compute pipeline for updating particle positions - vks::Buffer uniformBuffer; // Uniform buffer object containing particle system parameters - struct UniformData { // Compute shader uniform block object - float deltaT; // Frame delta time - float destX; // x position of the attractor - float destY; // y position of the attractor - int32_t particleCount = PARTICLE_COUNT; - } uniformData; - } compute; - - VulkanExample() : VulkanExampleBase() - { - title = "Compute shader particle system"; - } - - ~VulkanExample() - { - if (device) { - // Graphics - vkDestroyPipeline(device, graphics.pipeline, nullptr); - vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, graphics.descriptorSetLayout, nullptr); - vkDestroySemaphore(device, graphics.semaphore, nullptr); - - // Compute - compute.uniformBuffer.destroy(); - vkDestroyPipelineLayout(device, compute.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, compute.descriptorSetLayout, nullptr); - vkDestroyPipeline(device, compute.pipeline, nullptr); - vkDestroySemaphore(device, compute.semaphore, nullptr); - vkDestroyCommandPool(device, compute.commandPool, nullptr); - - storageBuffer.destroy(); - textures.particle.destroy(); - textures.gradient.destroy(); - } - } - - void loadAssets() - { - textures.particle.loadFromFile(getAssetPath() + "textures/particle01_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.gradient.loadFromFile(getAssetPath() + "textures/particle_gradient_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Acquire barrier - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - 0, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - compute.queueFamilyIndex, - graphics.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - // Draw the particle system using the update vertex buffer - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipelineLayout, 0, 1, &graphics.descriptorSet, 0, NULL); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &storageBuffer.buffer, offsets); - vkCmdDraw(drawCmdBuffers[i], PARTICLE_COUNT, 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - // Release barrier - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - 0, - graphics.queueFamilyIndex, - compute.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - - } - - void buildComputeCommandBuffer() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(compute.commandBuffer, &cmdBufInfo)); - - // Compute particle movement - - // Add memory barrier to ensure that the (graphics) vertex shader has fetched attributes before compute starts to write to the buffer - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - 0, - VK_ACCESS_SHADER_WRITE_BIT, - graphics.queueFamilyIndex, - compute.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - // Dispatch the compute job - vkCmdBindPipeline(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipeline); - vkCmdBindDescriptorSets(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineLayout, 0, 1, &compute.descriptorSet, 0, 0); - vkCmdDispatch(compute.commandBuffer, PARTICLE_COUNT / 256, 1, 1); - - // Add barrier to ensure that compute shader has finished writing to the buffer - // Without this the (rendering) vertex shader may display incomplete results (partial data from last frame) - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_SHADER_WRITE_BIT, - 0, - compute.queueFamilyIndex, - graphics.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - vkEndCommandBuffer(compute.commandBuffer); - } - - // Setup and fill the compute shader storage buffers containing the particles - void prepareStorageBuffers() - { - std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::uniform_real_distribution rndDist(-1.0f, 1.0f); - - // Initial particle positions - std::vector particleBuffer(PARTICLE_COUNT); - for (auto& particle : particleBuffer) { - particle.pos = glm::vec2(rndDist(rndEngine), rndDist(rndEngine)); - particle.vel = glm::vec2(0.0f); - particle.gradientPos.x = particle.pos.x / 2.0f; - } - - VkDeviceSize storageBufferSize = particleBuffer.size() * sizeof(Particle); - - // Staging - // SSBO won't be changed on the host after upload so copy to device local memory - - vks::Buffer stagingBuffer; - - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - storageBufferSize, - particleBuffer.data()); - - vulkanDevice->createBuffer( - // The SSBO will be used as a storage buffer for the compute pipeline and as a vertex buffer in the graphics pipeline - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &storageBuffer, - storageBufferSize); - - // Copy from staging buffer to storage buffer - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = {}; - copyRegion.size = storageBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, storageBuffer.buffer, 1, ©Region); - // Execute a transfer barrier to the compute queue, if necessary - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - 0, - graphics.queueFamilyIndex, - compute.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - copyCmd, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - stagingBuffer.destroy(); - } - - // The descriptor pool will be shared between graphics and compute - void setupDescriptorPool() - { - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - } - - void prepareGraphics() - { - prepareStorageBuffers(); - prepareUniformBuffers(); - - // Descriptor set layout - std::vector setLayoutBindings = { - // Binding 0 : Particle color map - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // Binding 1 : Particle gradient ramp - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &graphics.descriptorSetLayout)); - - // Descriptor set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &graphics.descriptorSet)); - - std::vector writeDescriptorSets; - // Binding 0 : Particle color map - writeDescriptorSets.push_back(vks::initializers::writeDescriptorSet( - graphics.descriptorSet, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 0, - &textures.particle.descriptor)); - // Binding 1 : Particle gradient ramp - writeDescriptorSets.push_back(vks::initializers::writeDescriptorSet( - graphics.descriptorSet, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 1, - &textures.gradient.descriptor)); - - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - - // Pipeline layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &graphics.pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_ALWAYS); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Vertex Input state - std::vector inputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Particle), VK_VERTEX_INPUT_RATE_VERTEX) - }; - std::vector inputAttributes = { - // Location 0 : Position - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Particle, pos)), - // Location 1 : Velocity (used for color gradient lookup) - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Particle, gradientPos)), - }; - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(inputBindings.size()); - vertexInputState.pVertexBindingDescriptions = inputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(inputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = inputAttributes.data(); - - shaderStages[0] = loadShader(getShadersPath() + "computeparticles/particle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "computeparticles/particle.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(graphics.pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &vertexInputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - pipelineCreateInfo.renderPass = renderPass; - - // Additive blending - blendAttachmentState.colorWriteMask = 0xF; - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &graphics.pipeline)); - - // Semaphore for compute & graphics sync - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &graphics.semaphore)); - - // Signal the semaphore - VkSubmitInfo submitInfo = vks::initializers::submitInfo(); - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = &graphics.semaphore; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VK_CHECK_RESULT(vkQueueWaitIdle(queue)); - } - - void prepareCompute() - { - // Create a compute capable device queue - // The VulkanDevice::createLogicalDevice functions finds a compute capable queue and prefers queue families that only support compute - // Depending on the implementation this may result in different queue family indices for graphics and computes, - // requiring proper synchronization (see the memory and pipeline barriers) - vkGetDeviceQueue(device, compute.queueFamilyIndex, 0, &compute.queue); - - // Create compute pipeline - // Compute pipelines are created separate from graphics pipelines even if they use the same queue (family index) - - std::vector setLayoutBindings = { - // Binding 0 : Particle position storage buffer - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - VK_SHADER_STAGE_COMPUTE_BIT, - 0), - // Binding 1 : Uniform buffer - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - VK_SHADER_STAGE_COMPUTE_BIT, - 1), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &compute.descriptorSetLayout)); - - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &compute.descriptorSetLayout,1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &compute.descriptorSet)); - std::vector computeWriteDescriptorSets = { - // Binding 0 : Particle position storage buffer - vks::initializers::writeDescriptorSet( - compute.descriptorSet, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - 0, - &storageBuffer.descriptor), - // Binding 1 : Uniform buffer - vks::initializers::writeDescriptorSet( - compute.descriptorSet, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - 1, - &compute.uniformBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(computeWriteDescriptorSets.size()), computeWriteDescriptorSets.data(), 0, NULL); - - // Create pipeline - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &compute.pipelineLayout)); - VkComputePipelineCreateInfo computePipelineCreateInfo = vks::initializers::computePipelineCreateInfo(compute.pipelineLayout, 0); - computePipelineCreateInfo.stage = loadShader(getShadersPath() + "computeparticles/particle.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT); - VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &compute.pipeline)); - - // Separate command pool as queue family for compute may be different than graphics - VkCommandPoolCreateInfo cmdPoolInfo = {}; - cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmdPoolInfo.queueFamilyIndex = compute.queueFamilyIndex; - cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &compute.commandPool)); - - // Create a command buffer for compute operations - compute.commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, compute.commandPool); - - // Semaphore for compute & graphics sync - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore)); - - // Build a single command buffer containing the compute dispatch commands - buildComputeCommandBuffer(); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Compute shader uniform buffer block - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &compute.uniformBuffer, sizeof(Compute::UniformData)); - // Map for host access - VK_CHECK_RESULT(compute.uniformBuffer.map()); - - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - compute.uniformData.deltaT = paused ? 0.0f : frameTimer * 2.5f; - if (!attachToCursor) - { - compute.uniformData.destX = sin(glm::radians(timer * 360.0f)) * 0.75f; - compute.uniformData.destY = 0.0f; - } - else - { - float normalizedMx = (mouseState.position.x - static_cast(width / 2)) / static_cast(width / 2); - float normalizedMy = (mouseState.position.y - static_cast(height / 2)) / static_cast(height / 2); - compute.uniformData.destX = normalizedMx; - compute.uniformData.destY = normalizedMy; - } - - memcpy(compute.uniformBuffer.mapped, &compute.uniformData, sizeof(Compute::UniformData)); - } - - void draw() - { - // Wait for rendering finished - VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - - // Submit compute commands - VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; - computeSubmitInfo.waitSemaphoreCount = 1; - computeSubmitInfo.pWaitSemaphores = &graphics.semaphore; - computeSubmitInfo.pWaitDstStageMask = &waitStageMask; - computeSubmitInfo.signalSemaphoreCount = 1; - computeSubmitInfo.pSignalSemaphores = &compute.semaphore; - VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::prepareFrame(); - - VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - VkSemaphore graphicsWaitSemaphores[] = { compute.semaphore, semaphores.presentComplete }; - VkSemaphore graphicsSignalSemaphores[] = { graphics.semaphore, semaphores.renderComplete }; - - // Submit graphics commands - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - submitInfo.waitSemaphoreCount = 2; - submitInfo.pWaitSemaphores = graphicsWaitSemaphores; - submitInfo.pWaitDstStageMask = graphicsWaitStageMasks; - submitInfo.signalSemaphoreCount = 2; - submitInfo.pSignalSemaphores = graphicsSignalSemaphores; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - // We will be using the queue family indices to check if graphics and compute queue families differ - // If that's the case, we need additional barriers for acquiring and releasing resources - graphics.queueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - compute.queueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - loadAssets(); - setupDescriptorPool(); - prepareGraphics(); - prepareCompute(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - draw(); - - if (!attachToCursor) - { - if (animStart > 0.0f) - { - animStart -= frameTimer * 5.0f; - } - else if (animStart <= 0.0f) - { - timer += frameTimer * 0.04f; - if (timer > 1.f) - timer = 0.f; - } - } - - updateUniformBuffers(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->checkBox("Attach attractor to cursor", &attachToCursor); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/computeraytracing/computeraytracing.cpp b/examples/computeraytracing/computeraytracing.cpp deleted file mode 100644 index cab1f861..00000000 --- a/examples/computeraytracing/computeraytracing.cpp +++ /dev/null @@ -1,630 +0,0 @@ -/* -* Vulkan Example - Compute shader based ray tracing -* -* This samples implements a basic ray tracer with materials and reflections using a compute shader -* Shader storage buffers are used to pass geometry information for spheres and planes to the computer shader -* The compute shader then uses these as the scene geometry for ray tracing and outputs the results to a storage image -* The graphics part of the sample then displays that image full screen -* Not to be confused with actual hardware accelerated ray tracing -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - // The compute shader will store the ray traced output to a storage image - vks::Texture storageImage{}; - - // Resources for the graphics part of the example. The graphics pipeline simply displays the compute shader output - struct Graphics { - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - } graphics; - - // Resources for the compute part of the example - struct Compute { - // Object properties for planes and spheres are passed via a shade storage buffer - // There is no vertex data, the compute shader calculates the primitives on the fly - vks::Buffer objectStorageBuffer; - vks::Buffer uniformBuffer; // Uniform buffer object containing scene parameters - VkQueue queue{ VK_NULL_HANDLE }; // Separate queue for compute commands (queue family may differ from the one used for graphics) - VkCommandPool commandPool{ VK_NULL_HANDLE }; // Use a separate command pool (queue family may differ from the one used for graphics) - VkCommandBuffer commandBuffer{ VK_NULL_HANDLE }; // Command buffer storing the dispatch commands and barriers - VkFence fence{ VK_NULL_HANDLE }; // Synchronization fence to avoid rewriting compute CB if still in use - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; // Compute shader binding layout - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; // Compute shader bindings - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; // Layout of the compute pipeline - VkPipeline pipeline{ VK_NULL_HANDLE }; // Compute raytracing pipeline - struct UniformDataCompute { // Compute shader uniform block object - glm::vec3 lightPos; - float aspectRatio{ 1.0f }; - glm::vec4 fogColor = glm::vec4(0.0f); - struct { - glm::vec3 pos = glm::vec3(0.0f, 0.0f, 4.0f); - glm::vec3 lookat = glm::vec3(0.0f, 0.5f, 0.0f); - float fov = 10.0f; - } camera; - glm::mat4 _pad; - } uniformData; - } compute; - - // Definitions for scene objects - // The sample uses spheres and planes that are passed to the compute shader via a shader storage buffer - // The computer shader uses the object type to select different calculations - enum class SceneObjectType { Sphere = 0, Plane = 1 }; - // Spheres and planes are described by different properties, we use a union for this - union SceneObjectProperty { - glm::vec4 positionAndRadius; - glm::vec4 normalAndDistance; - }; - struct SceneObject { - SceneObjectProperty objectProperties{}; - glm::vec3 diffuse; - float specular{ 1.0f }; - uint32_t id{ 0 }; - uint32_t objectType{ 0 }; - // Due to alignment rules we need to pad to make the element align at 16-bytes - glm::ivec2 _pad; - }; - - VulkanExample() : VulkanExampleBase() - { - title = "Compute shader ray tracing"; - timerSpeed *= 0.25f; - - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -4.0f)); - camera.rotationSpeed = 0.0f; - camera.movementSpeed = 2.5f; - } - - ~VulkanExample() - { - if (device) { - // Graphics - vkDestroyPipeline(device, graphics.pipeline, nullptr); - vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, graphics.descriptorSetLayout, nullptr); - - // Compute - vkDestroyPipeline(device, compute.pipeline, nullptr); - vkDestroyPipelineLayout(device, compute.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, compute.descriptorSetLayout, nullptr); - vkDestroyFence(device, compute.fence, nullptr); - vkDestroyCommandPool(device, compute.commandPool, nullptr); - compute.uniformBuffer.destroy(); - compute.objectStorageBuffer.destroy(); - - storageImage.destroy(); - } - } - - // Prepare a storage image that is used to store the compute shader ray tracing output - void prepareStorageImage() - { -#if defined(__ANDROID__) - // Use a smaller image on Android for performance reasons - const uint32_t textureSize = 1024; -#else - const uint32_t textureSize = 2048; -#endif - - const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; - - // Get device properties for the requested texture format - VkFormatProperties formatProperties; - vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties); - // Check if requested image format supports image storage operations required for storing pixel from the compute shader - assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT); - - // Prepare blit target texture - storageImage.width = textureSize; - storageImage.height = textureSize; - - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.extent = { textureSize, textureSize, 1 }; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - // Image will be sampled in the fragment shader and used as storage target in the compute shader - imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT; - imageCreateInfo.flags = 0; - - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &storageImage.image)); - vkGetImageMemoryRequirements(device, storageImage.image, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &storageImage.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, storageImage.image, storageImage.deviceMemory, 0)); - - VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - storageImage.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - vks::tools::setImageLayout(layoutCmd, storageImage.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, storageImage.imageLayout); - // Add an initial release barrier to the graphics queue, - // so that when the compute command buffer executes for the first time - // it doesn't complain about a lack of a corresponding "release" to its "acquire" - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) - { - VkImageMemoryBarrier imageMemoryBarrier = {}; - imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - imageMemoryBarrier.image = storageImage.image; - imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = 0; - imageMemoryBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - imageMemoryBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - vkCmdPipelineBarrier( - layoutCmd, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); - } - vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); - - // Create sampler - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 1.0f; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = 0.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &storageImage.sampler)); - - // Create image view - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.format = format; - view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - view.image = storageImage.image; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &storageImage.view)); - - // Initialize a descriptor for later use - storageImage.descriptor.imageLayout = storageImage.imageLayout; - storageImage.descriptor.imageView = storageImage.view; - storageImage.descriptor.sampler = storageImage.sampler; - storageImage.device = vulkanDevice; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Image memory barrier to make sure that compute shader writes are finished before sampling from the texture - VkImageMemoryBarrier imageMemoryBarrier = {}; - imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - imageMemoryBarrier.image = storageImage.image; - imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) - { - // Acquire barrier for graphics queue - imageMemoryBarrier.srcAccessMask = 0; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - imageMemoryBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); - } - else - { - // Combined barrier on single queue family - imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); - } - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Display ray traced image generated by compute shader as a full screen quad - // Quad vertices are generated in the vertex shader - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipelineLayout, 0, 1, &graphics.descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipeline); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) - { - // Release barrier from graphics queue - imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = 0; - imageMemoryBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - imageMemoryBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - - } - - void buildComputeCommandBuffer() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(compute.commandBuffer, &cmdBufInfo)); - - VkImageMemoryBarrier imageMemoryBarrier = {}; - imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - imageMemoryBarrier.image = storageImage.image; - imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) - { - // Acquire barrier for compute queue - imageMemoryBarrier.srcAccessMask = 0; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - imageMemoryBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - imageMemoryBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); - } - - vkCmdBindPipeline(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipeline); - vkCmdBindDescriptorSets(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineLayout, 0, 1, &compute.descriptorSet, 0, 0); - - vkCmdDispatch(compute.commandBuffer, storageImage.width / 16, storageImage.height / 16, 1); - - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) - { - // Release barrier from compute queue - imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = 0; - imageMemoryBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - imageMemoryBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); - } - - vkEndCommandBuffer(compute.commandBuffer); - } - - // Setup and fill the compute shader storage buffes containing object definitions for the raytraced scene - void prepareStorageBuffers() - { - // Id used to identify objects by the ray tracing shader - uint32_t currentId = 0; - - std::vector sceneObjects{}; - - // Add some spheres to the scene - //std::vector spheres; - // Lambda to simplify object creation - auto addSphere = [&sceneObjects, ¤tId](glm::vec3 pos, float radius, glm::vec3 diffuse, float specular) { - SceneObject sphere{}; - sphere.id = currentId++; - sphere.objectProperties.positionAndRadius = glm::vec4(pos, radius); - sphere.diffuse = diffuse; - sphere.specular = specular; - sphere.objectType = (uint32_t)SceneObjectType::Sphere; - sceneObjects.push_back(sphere); - }; - - auto addPlane = [&sceneObjects, ¤tId](glm::vec3 normal, float distance, glm::vec3 diffuse, float specular) { - SceneObject plane{}; - plane.id = currentId++; - plane.objectProperties.normalAndDistance = glm::vec4(normal, distance); - plane.diffuse = diffuse; - plane.specular = specular; - plane.objectType = (uint32_t)SceneObjectType::Plane; - sceneObjects.push_back(plane); - }; - - addSphere(glm::vec3(1.75f, -0.5f, 0.0f), 1.0f, glm::vec3(0.0f, 1.0f, 0.0f), 32.0f); - addSphere(glm::vec3(0.0f, 1.0f, -0.5f), 1.0f, glm::vec3(0.65f, 0.77f, 0.97f), 32.0f); - addSphere(glm::vec3(-1.75f, -0.75f, -0.5f), 1.25f, glm::vec3(0.9f, 0.76f, 0.46f), 32.0f); - - const float roomDim = 4.0f; - addPlane(glm::vec3(0.0f, 1.0f, 0.0f), roomDim, glm::vec3(1.0f), 32.0f); - addPlane(glm::vec3(0.0f, -1.0f, 0.0f), roomDim, glm::vec3(1.0f), 32.0f); - addPlane(glm::vec3(0.0f, 0.0f, 1.0f), roomDim, glm::vec3(1.0f), 32.0f); - addPlane(glm::vec3(0.0f, 0.0f, -1.0f), roomDim, glm::vec3(0.0f), 32.0f); - addPlane(glm::vec3(-1.0f, 0.0f, 0.0f), roomDim, glm::vec3(1.0f, 0.0f, 0.0f), 32.0f); - addPlane(glm::vec3(1.0f, 0.0f, 0.0f), roomDim, glm::vec3(0.0f, 1.0f, 0.0f), 32.0f); - - VkDeviceSize storageBufferSize = sceneObjects.size() * sizeof(SceneObject); - - // Copy the data to the device - vks::Buffer stagingBuffer; - vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer, storageBufferSize, sceneObjects.data()); - vulkanDevice->createBuffer(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &compute.objectStorageBuffer, storageBufferSize); - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = { 0, 0, storageBufferSize}; - vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, compute.objectStorageBuffer.buffer, 1, ©Region); - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - stagingBuffer.destroy(); - } - - // The descriptor pool will be shared between graphics and compute - void setupDescriptorPool() - { - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - } - - // Prepare the graphics resources used to display the ray traced output of the compute shader - void prepareGraphics() - { - // Setup descriptors - - // The graphics pipeline uses one set and one binding - // Binding 0: Storage image with raytraced output as a sampled image for displaying it - - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &graphics.descriptorSetLayout)); - - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &graphics.descriptorSet)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(graphics.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &storageImage.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &graphics.pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_FRONT_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - shaderStages[0] = loadShader(getShadersPath() + "computeraytracing/texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "computeraytracing/texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkPipelineVertexInputStateCreateInfo emptyInputState{}; - emptyInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(graphics.pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &emptyInputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - pipelineCreateInfo.renderPass = renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &graphics.pipeline)); - } - - // Prepare the compute resources that generates the ray traced image - void prepareCompute() - { - // Create a compute capable device queue - // The VulkanDevice::createLogicalDevice functions finds a compute capable queue and prefers queue families that only support compute - // Depending on the implementation this may result in different queue family indices for graphics and computes, - // requiring proper synchronization (see the memory barriers in buildComputeCommandBuffer) - VkDeviceQueueCreateInfo queueCreateInfo = {}; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.pNext = NULL; - queueCreateInfo.queueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - queueCreateInfo.queueCount = 1; - vkGetDeviceQueue(device, vulkanDevice->queueFamilyIndices.compute, 0, &compute.queue); - - // Setup descriptors - - // The compute pipeline uses one set and four bindings - // Binding 0: Storage image for raytraced output - // Binding 1: Uniform buffer with parameters - // Binding 2: Shader storage buffer with scene object definitions - - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 1), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 2), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &compute.descriptorSetLayout)); - - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &compute.descriptorSet)); - std::vector computeWriteDescriptorSets = { - vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 0, &storageImage.descriptor), - vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, &compute.uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2, &compute.objectStorageBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(computeWriteDescriptorSets.size()), computeWriteDescriptorSets.data(), 0, nullptr); - - // Create the compute shader pipeline - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &compute.pipelineLayout)); - - VkComputePipelineCreateInfo computePipelineCreateInfo = vks::initializers::computePipelineCreateInfo(compute.pipelineLayout, 0); - computePipelineCreateInfo.stage = loadShader(getShadersPath() + "computeraytracing/raytracing.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT); - VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &compute.pipeline)); - - // Separate command pool as queue family for compute may be different from the graphics one - VkCommandPoolCreateInfo cmdPoolInfo = {}; - cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmdPoolInfo.queueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &compute.commandPool)); - - // Create a command buffer for compute operations - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(compute.commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &compute.commandBuffer)); - - // Fence for compute CB sync - VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(); - VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &compute.fence)); - - // Build a single command buffer containing the compute dispatch commands - buildComputeCommandBuffer(); - } - - void prepareUniformBuffers() - { - // Compute shader parameter uniform buffer block - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &compute.uniformBuffer, sizeof(Compute::UniformDataCompute)); - } - - void updateUniformBuffers() - { - compute.uniformData.aspectRatio = (float)width / (float)height; - compute.uniformData.lightPos.x = 0.0f + sin(glm::radians(timer * 360.0f)) * cos(glm::radians(timer * 360.0f)) * 2.0f; - compute.uniformData.lightPos.y = 0.0f + sin(glm::radians(timer * 360.0f)) * 2.0f; - compute.uniformData.lightPos.z = 0.0f + cos(glm::radians(timer * 360.0f)) * 2.0f; - compute.uniformData.camera.pos = camera.position * -1.0f; - VK_CHECK_RESULT(compute.uniformBuffer.map()); - memcpy(compute.uniformBuffer.mapped, &compute.uniformData, sizeof(Compute::UniformDataCompute)); - compute.uniformBuffer.unmap(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - prepareStorageImage(); - prepareStorageBuffers(); - prepareUniformBuffers(); - setupDescriptorPool(); - prepareGraphics(); - prepareCompute(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - // Submit compute commands - // Use a fence to ensure that compute command buffer has finished executing before using it again - VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; - - VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, compute.fence)); - - vkWaitForFences(device, 1, &compute.fence, VK_TRUE, UINT64_MAX); - vkResetFences(device, 1, &compute.fence); - - VulkanExampleBase::prepareFrame(); - - // Command buffer to be submitted to the queue - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/computeshader/computeshader.cpp b/examples/computeshader/computeshader.cpp deleted file mode 100644 index 42c8c07e..00000000 --- a/examples/computeshader/computeshader.cpp +++ /dev/null @@ -1,582 +0,0 @@ -/* -* Vulkan Example - Compute shader image processing -* -* This sample uses a compute shader to apply different filters to an image -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -// Vertex layout for this example -struct Vertex { - float pos[3]; - float uv[2]; -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - // Input image - vks::Texture2D textureColorMap; - // Storage image that the compute shader uses to apply the filter effect to - vks::Texture2D storageImage; - - // Resources for the graphics part of the example - struct Graphics { - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; // Image display shader binding layout - VkDescriptorSet descriptorSetPreCompute{ VK_NULL_HANDLE }; // Image display shader bindings before compute shader image manipulation - VkDescriptorSet descriptorSetPostCompute{ VK_NULL_HANDLE }; // Image display shader bindings after compute shader image manipulation - VkPipeline pipeline{ VK_NULL_HANDLE }; // Image display pipeline - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; // Layout of the graphics pipeline - VkSemaphore semaphore{ VK_NULL_HANDLE }; // Execution dependency between compute & graphic submission - // Used to pass data to the graphics shaders - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - } uniformData; - vks::Buffer uniformBuffer; - } graphics; - - // Resources for the compute part of the example - struct Compute { - VkQueue queue{ VK_NULL_HANDLE }; // Separate queue for compute commands (queue family may differ from the one used for graphics) - VkCommandPool commandPool{ VK_NULL_HANDLE }; // Use a separate command pool (queue family may differ from the one used for graphics) - VkCommandBuffer commandBuffer{ VK_NULL_HANDLE }; // Command buffer storing the dispatch commands and barriers - VkSemaphore semaphore{ VK_NULL_HANDLE }; // Execution dependency between compute & graphic submission - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; // Compute shader binding layout - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; // Compute shader bindings - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; // Layout of the compute pipeline - std::vector pipelines{}; // Compute pipelines for image filters - int32_t pipelineIndex{ 0 }; // Current image filtering compute pipeline index - } compute; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount{ 0 }; - uint32_t vertexBufferSize{ 0 }; - - std::vector filterNames{}; - - VulkanExample() : VulkanExampleBase() - { - title = "Compute shader image load/store"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -2.0f)); - camera.setRotation(glm::vec3(0.0f)); - camera.setPerspective(60.0f, (float)width * 0.5f / (float)height, 1.0f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - // Graphics - vkDestroyPipeline(device, graphics.pipeline, nullptr); - vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, graphics.descriptorSetLayout, nullptr); - vkDestroySemaphore(device, graphics.semaphore, nullptr); - graphics.uniformBuffer.destroy(); - - // Compute - for (auto& pipeline : compute.pipelines) - { - vkDestroyPipeline(device, pipeline, nullptr); - } - vkDestroyPipelineLayout(device, compute.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, compute.descriptorSetLayout, nullptr); - vkDestroySemaphore(device, compute.semaphore, nullptr); - vkDestroyCommandPool(device, compute.commandPool, nullptr); - - vertexBuffer.destroy(); - indexBuffer.destroy(); - - textureColorMap.destroy(); - storageImage.destroy(); - } - } - - // Prepare a storage image that is used to store the compute shader filter - void prepareStorageImage() - { - const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; - - VkFormatProperties formatProperties; - // Get device properties for the requested texture format - vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties); - // Check if requested image format supports image storage operations required for storing pixel from the compute shader - assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT); - - // Prepare blit target texture - storageImage.width = textureColorMap.width; - storageImage.height = textureColorMap.height; - - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.extent = { storageImage.width, storageImage.height, 1 }; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - // Image will be sampled in the fragment shader and used as storage target in the compute shader - imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT; - imageCreateInfo.flags = 0; - // If compute and graphics queue family indices differ, we create an image that can be shared between them - // This can result in worse performance than exclusive sharing mode, but save some synchronization to keep the sample simple - std::vector queueFamilyIndices; - if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) { - queueFamilyIndices = { - vulkanDevice->queueFamilyIndices.graphics, - vulkanDevice->queueFamilyIndices.compute - }; - imageCreateInfo.sharingMode = VK_SHARING_MODE_CONCURRENT; - imageCreateInfo.queueFamilyIndexCount = 2; - imageCreateInfo.pQueueFamilyIndices = queueFamilyIndices.data(); - } - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &storageImage.image)); - - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, storageImage.image, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &storageImage.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, storageImage.image, storageImage.deviceMemory, 0)); - - // Transition image to the general layout, so we can use it as a storage image in the compute shader - VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - storageImage.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - vks::tools::setImageLayout(layoutCmd, storageImage.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, storageImage.imageLayout); - vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); - - // Create sampler - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 1.0f; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = 1.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &storageImage.sampler)); - - // Create image view - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.image = VK_NULL_HANDLE; - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.format = format; - view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - view.image = storageImage.image; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &storageImage.view)); - - // Initialize a descriptor for later use - storageImage.descriptor.imageLayout = storageImage.imageLayout; - storageImage.descriptor.imageView = storageImage.view; - storageImage.descriptor.sampler = storageImage.sampler; - storageImage.device = vulkanDevice; - } - - void loadAssets() - { - textureColorMap.loadFromFile(getAssetPath() + "textures/vulkan_11_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Image memory barrier to make sure that compute shader writes are finished before sampling from the texture - VkImageMemoryBarrier imageMemoryBarrier = {}; - imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - // We won't be changing the layout of the image - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - imageMemoryBarrier.image = storageImage.image; - imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width * 0.5f, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &vertexBuffer.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); - - // Left (pre compute) - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipelineLayout, 0, 1, &graphics.descriptorSetPreCompute, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipeline); - - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); - - // Right (post compute) - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipelineLayout, 0, 1, &graphics.descriptorSetPostCompute, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipeline); - - viewport.x = (float)width / 2.0f; - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - - } - - void buildComputeCommandBuffer() - { - // Flush the queue if we're rebuilding the command buffer after a pipeline change to ensure it's not currently in use - vkQueueWaitIdle(compute.queue); - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(compute.commandBuffer, &cmdBufInfo)); - - vkCmdBindPipeline(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelines[compute.pipelineIndex]); - vkCmdBindDescriptorSets(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineLayout, 0, 1, &compute.descriptorSet, 0, 0); - - vkCmdDispatch(compute.commandBuffer, storageImage.width / 16, storageImage.height / 16, 1); - - vkEndCommandBuffer(compute.commandBuffer); - } - - // Setup vertices for a single uv-mapped quad used to display the input and output images - void generateQuad() - { - // Setup vertices for a single uv-mapped quad made from two triangles - std::vector vertices = { - { { 1.0f, 1.0f, 0.0f }, { 1.0f, 1.0f } }, - { { -1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f } }, - { { -1.0f, -1.0f, 0.0f }, { 0.0f, 0.0f } }, - { { 1.0f, -1.0f, 0.0f }, { 1.0f, 0.0f } } - }; - - // Setup indices - std::vector indices = { 0,1,2, 2,3,0 }; - indexCount = static_cast(indices.size()); - - // Create buffers and upload data to the GPU - - struct StagingBuffers { - vks::Buffer vertices; - vks::Buffer indices; - } stagingBuffers; - - // Host visible source buffers (staging) - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.vertices, vertices.size() * sizeof(Vertex), vertices.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.indices, indices.size() * sizeof(uint32_t), indices.data())); - - // Device local destination buffers - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &vertexBuffer, vertices.size() * sizeof(Vertex))); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &indexBuffer, indices.size() * sizeof(uint32_t))); - - // Copy from host do device - vulkanDevice->copyBuffer(&stagingBuffers.vertices, &vertexBuffer, queue); - vulkanDevice->copyBuffer(&stagingBuffers.indices, &indexBuffer, queue); - - // Clean up - stagingBuffers.vertices.destroy(); - stagingBuffers.indices.destroy(); - } - - // The descriptor pool will be shared between graphics and compute - void setupDescriptorPool() - { - std::vector poolSizes = { - // Graphics pipelines uniform buffers - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - // Graphics pipelines image samplers for displaying compute output image - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2), - // Compute pipelines uses a storage image for image reads and writes - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - } - - // Prepare the graphics resources used to display the ray traced output of the compute shader - void prepareGraphics() - { - // Create a semaphore for compute & graphics sync - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &graphics.semaphore)); - - // Signal the semaphore - VkSubmitInfo submitInfo = vks::initializers::submitInfo(); - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = &graphics.semaphore; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VK_CHECK_RESULT(vkQueueWaitIdle(queue)); - - // Setup descriptors - - // The graphics pipeline uses two sets with two bindings - // One set for displaying the input image and one set for displaying the output image with the compute filter applied - // Binding 0: Vertex shader uniform buffer - // Binding 1: Sampled image (before/after compute filter is applied) - - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &graphics.descriptorSetLayout)); - - VkDescriptorSetAllocateInfo allocInfo = - vks::initializers::descriptorSetAllocateInfo(descriptorPool, &graphics.descriptorSetLayout, 1); - - // Input image (before compute post processing) - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &graphics.descriptorSetPreCompute)); - std::vector baseImageWriteDescriptorSets = { - vks::initializers::writeDescriptorSet(graphics.descriptorSetPreCompute, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &graphics.uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(graphics.descriptorSetPreCompute, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textureColorMap.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(baseImageWriteDescriptorSets.size()), baseImageWriteDescriptorSets.data(), 0, nullptr); - - // Final image (after compute shader processing) - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &graphics.descriptorSetPostCompute)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(graphics.descriptorSetPostCompute, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &graphics.uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(graphics.descriptorSetPostCompute, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &storageImage.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Graphics pipeline used to display the images (before and after the compute effect is applied) - - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &graphics.pipelineLayout)); - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Shaders - shaderStages[0] = loadShader(getShadersPath() + "computeshader/texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "computeshader/texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - // Vertex input state - std::vector vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX) - }; - std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)), - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)), - }; - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(graphics.pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &vertexInputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &graphics.pipeline)); - } - - void prepareCompute() - { - // Get a compute queue from the device - vkGetDeviceQueue(device, vulkanDevice->queueFamilyIndices.compute, 0, &compute.queue); - - // Create compute pipeline - // Compute pipelines are created separate from graphics pipelines even if they use the same queue - - std::vector setLayoutBindings = { - // Binding 0: Input image (read-only) - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 0), - // Binding 1: Output image (write) - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 1), - }; - - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &compute.descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &compute.pipelineLayout)); - - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &compute.descriptorSet)); - std::vector computeWriteDescriptorSets = { - vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 0, &textureColorMap.descriptor), - vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImage.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(computeWriteDescriptorSets.size()), computeWriteDescriptorSets.data(), 0, nullptr); - - // Create compute shader pipelines - VkComputePipelineCreateInfo computePipelineCreateInfo = vks::initializers::computePipelineCreateInfo(compute.pipelineLayout, 0); - - // One pipeline for each available image filter - filterNames = { "emboss", "edgedetect", "sharpen" }; - for (auto& shaderName : filterNames) { - std::string fileName = getShadersPath() + "computeshader/" + shaderName + ".comp.spv"; - computePipelineCreateInfo.stage = loadShader(fileName, VK_SHADER_STAGE_COMPUTE_BIT); - VkPipeline pipeline; - VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &pipeline)); - compute.pipelines.push_back(pipeline); - } - - // Separate command pool as queue family for compute may be different than graphics - VkCommandPoolCreateInfo cmdPoolInfo = {}; - cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmdPoolInfo.queueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &compute.commandPool)); - - // Create a command buffer for compute operations - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo( compute.commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &compute.commandBuffer)); - - // Semaphore for compute & graphics sync - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore)); - - // Build a single command buffer containing the compute dispatch commands - buildComputeCommandBuffer(); - } - - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &graphics.uniformBuffer, sizeof(Graphics::UniformData))); - // Map persistent - VK_CHECK_RESULT(graphics.uniformBuffer.map()); - } - - void updateUniformBuffers() - { - // We need to adjust the perspective as this sample displays two viewports side-by-side - camera.setPerspective(60.0f, (float)width * 0.5f / (float)height, 1.0f, 256.0f); - graphics.uniformData.projection = camera.matrices.perspective; - graphics.uniformData.modelView = camera.matrices.view; - memcpy(graphics.uniformBuffer.mapped, &graphics.uniformData, sizeof(Graphics::UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - generateQuad(); - prepareUniformBuffers(); - prepareStorageImage(); - setupDescriptorPool(); - prepareGraphics(); - prepareCompute(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - // Wait for rendering finished - VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - - // Submit compute commands - VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; - computeSubmitInfo.waitSemaphoreCount = 1; - computeSubmitInfo.pWaitSemaphores = &graphics.semaphore; - computeSubmitInfo.pWaitDstStageMask = &waitStageMask; - computeSubmitInfo.signalSemaphoreCount = 1; - computeSubmitInfo.pSignalSemaphores = &compute.semaphore; - VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::prepareFrame(); - - VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - VkSemaphore graphicsWaitSemaphores[] = { compute.semaphore, semaphores.presentComplete }; - VkSemaphore graphicsSignalSemaphores[] = { graphics.semaphore, semaphores.renderComplete }; - - // Submit graphics commands - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - submitInfo.waitSemaphoreCount = 2; - submitInfo.pWaitSemaphores = graphicsWaitSemaphores; - submitInfo.pWaitDstStageMask = graphicsWaitStageMasks; - submitInfo.signalSemaphoreCount = 2; - submitInfo.pSignalSemaphores = graphicsSignalSemaphores; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - { - return; - } - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->comboBox("Shader", &compute.pipelineIndex, filterNames)) { - buildComputeCommandBuffer(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/conditionalrender/conditionalrender.cpp b/examples/conditionalrender/conditionalrender.cpp deleted file mode 100644 index e180c809..00000000 --- a/examples/conditionalrender/conditionalrender.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* -* Vulkan Example - Conditional rendering -* -* Note: Requires a device that supports the VK_EXT_conditional_rendering extension -* -* With conditional rendering it's possible to execute certain rendering commands based on a buffer value instead of having to rebuild the command buffers. -* This example sets up a conditional buffer with one value per glTF part, that is used to toggle visibility of single model parts. -* -* Copyright (C) 2018-2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT{ VK_NULL_HANDLE }; - PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT{ VK_NULL_HANDLE }; - - vkglTF::Model scene; - - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - } uniformData; - vks::Buffer uniformBuffer; - - std::vector conditionalVisibility{}; - vks::Buffer conditionalBuffer; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Conditional rendering"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(45.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(-2.25f, -52.0f, 0.0f)); - camera.setTranslation(glm::vec3(1.9f, -2.05f, -18.0f)); - camera.rotationSpeed *= 0.25f; - - /* - [POI] Enable extension required for conditional rendering - */ - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - conditionalBuffer.destroy(); - } - } - - void renderNode(vkglTF::Node *node, VkCommandBuffer commandBuffer) { - if (node->mesh) { - for (vkglTF::Primitive * primitive : node->mesh->primitives) { - const std::vector descriptorsets = { - descriptorSet, - node->mesh->uniformBuffer.descriptorSet - }; - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, static_cast(descriptorsets.size()), descriptorsets.data(), 0, NULL); - - vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(primitive->material.baseColorFactor), &primitive->material.baseColorFactor); - - /* - [POI] Setup the conditional rendering - */ - VkConditionalRenderingBeginInfoEXT conditionalRenderingBeginInfo{}; - conditionalRenderingBeginInfo.sType = VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT; - conditionalRenderingBeginInfo.buffer = conditionalBuffer.buffer; - conditionalRenderingBeginInfo.offset = sizeof(int32_t) * node->index; - - /* - [POI] Begin conditionally rendered section - - If the value from the conditional rendering buffer at the given offset is != 0, the draw commands will be executed - */ - vkCmdBeginConditionalRenderingEXT(commandBuffer, &conditionalRenderingBeginInfo); - - vkCmdDrawIndexed(commandBuffer, primitive->indexCount, 1, primitive->firstIndex, 0, 0); - - vkCmdEndConditionalRenderingEXT(commandBuffer); - } - - }; - for (auto child : node->children) { - renderNode(child, commandBuffer); - } - } - - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 1.0f, 1.0f, 1.0f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - const VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &scene.vertices.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], scene.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - for (auto node : scene.nodes) { - renderNode(node, drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - scene.loadFromFile(getAssetPath() + "models/gltf/glTF-Embedded/Buggy.gltf", vulkanDevice, queue); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorPool)); - - // Layouts - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI{}; - descriptorLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptorLayoutCI.bindingCount = static_cast(setLayoutBindings.size()); - descriptorLayoutCI.pBindings = setLayoutBindings.data(); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayout)); - - // Sets - VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - std::array setLayouts = { - descriptorSetLayout, vkglTF::descriptorSetLayoutUbo - }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), 2); - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::vec4), 0); - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables, 0); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - const std::array shaderStages = { - loadShader(getShadersPath() + "conditionalrender/model.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "conditionalrender/model.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffer, - sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = glm::scale(camera.matrices.view, glm::vec3(0.1f , -0.1f, 0.1f)); - uniformData.model = glm::translate(glm::mat4(1.0f), scene.dimensions.min); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void updateConditionalBuffer() - { - memcpy(conditionalBuffer.mapped, conditionalVisibility.data(), sizeof(int32_t) * conditionalVisibility.size()); - } - - /* - [POI] Extension specific setup - - Gets the function pointers required for conditional rendering - Sets up a dedicated conditional buffer that is used to determine visibility at draw time - */ - void prepareConditionalRendering() - { - /* - The conditional rendering functions are part of an extension so they have to be loaded manually - */ - vkCmdBeginConditionalRenderingEXT = (PFN_vkCmdBeginConditionalRenderingEXT)vkGetDeviceProcAddr(device, "vkCmdBeginConditionalRenderingEXT"); - if (!vkCmdBeginConditionalRenderingEXT) { - vks::tools::exitFatal("Could not get a valid function pointer for vkCmdBeginConditionalRenderingEXT", -1); - } - - vkCmdEndConditionalRenderingEXT = (PFN_vkCmdEndConditionalRenderingEXT)vkGetDeviceProcAddr(device, "vkCmdEndConditionalRenderingEXT"); - if (!vkCmdEndConditionalRenderingEXT) { - vks::tools::exitFatal("Could not get a valid function pointer for vkCmdEndConditionalRenderingEXT", -1); - } - - /* - Create the buffer that contains the conditional rendering information - - A single conditional value is 32 bits and if it's zero the rendering commands are discarded - This sample renders multiple rows of objects conditionally, so we setup a buffer with one value per row - */ - conditionalVisibility.resize(scene.linearNodes.size()); - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &conditionalBuffer, - sizeof(int32_t) *conditionalVisibility.size(), - conditionalVisibility.data())); - VK_CHECK_RESULT(conditionalBuffer.map()); - - // By default, all parts of the glTF are visible - for (auto i = 0; i < conditionalVisibility.size(); i++) { - conditionalVisibility[i] = 1; - } - - /* - Copy visibility data - */ - updateConditionalBuffer(); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareConditionalRendering(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Visibility")) { - - if (overlay->button("All")) { - for (auto i = 0; i < conditionalVisibility.size(); i++) { - conditionalVisibility[i] = 1; - } - updateConditionalBuffer(); - } - ImGui::SameLine(); - if (overlay->button("None")) { - for (auto i = 0; i < conditionalVisibility.size(); i++) { - conditionalVisibility[i] = 0; - } - updateConditionalBuffer(); - } - ImGui::NewLine(); - - ImGui::BeginChild("InnerRegion", ImVec2(200.0f * overlay->scale, 400.0f * overlay->scale), false); - for (auto node : scene.linearNodes) { - // Add visibility toggle checkboxes for all model nodes with a mesh - if (node->mesh) { - if (overlay->checkBox(("[" + std::to_string(node->index) + "] " + node->mesh->name).c_str(), &conditionalVisibility[node->index])) { - updateConditionalBuffer(); - } - } - } - ImGui::EndChild(); - - } - } - -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/conservativeraster/conservativeraster.cpp b/examples/conservativeraster/conservativeraster.cpp deleted file mode 100644 index 63217393..00000000 --- a/examples/conservativeraster/conservativeraster.cpp +++ /dev/null @@ -1,686 +0,0 @@ -/* -* Vulkan Example - Conservative rasterization -* -* Note: Requires a device that supports the VK_EXT_conservative_rasterization extension -* -* Uses an offscreen buffer with lower resolution to demonstrate the effect of conservative rasterization -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - // Fetch and store conservative rasterization state props for display purposes - VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservativeRasterProps{}; - - bool conservativeRasterEnabled = true; - - struct Vertex { - float position[3]; - float color[3]; - }; - - struct Triangle { - vks::Buffer vertices; - vks::Buffer indices; - uint32_t indexCount{ 0 }; - } triangle; - - struct UniformData { - glm::mat4 projection; - glm::mat4 model; - } uniformData; - vks::Buffer uniformBuffer; - - struct PipelineLayouts { - VkPipelineLayout scene{ VK_NULL_HANDLE }; - VkPipelineLayout fullscreen{ VK_NULL_HANDLE }; - } pipelineLayouts; - - struct Pipelines { - VkPipeline triangle{ VK_NULL_HANDLE }; - VkPipeline triangleConservativeRaster{ VK_NULL_HANDLE }; - VkPipeline triangleOverlay{ VK_NULL_HANDLE }; - VkPipeline fullscreen{ VK_NULL_HANDLE }; - } pipelines; - - struct DescriptorSetLayouts { - VkDescriptorSetLayout scene{ VK_NULL_HANDLE }; - VkDescriptorSetLayout fullscreen{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - struct DescriptorSets { - VkDescriptorSet scene{ VK_NULL_HANDLE }; - VkDescriptorSet fullscreen{ VK_NULL_HANDLE }; - } descriptorSets; - - // Framebuffer for offscreen rendering - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory mem; - VkImageView view; - }; - struct OffscreenPass { - int32_t width, height; - VkFramebuffer frameBuffer; - FrameBufferAttachment color, depth; - VkRenderPass renderPass; - VkSampler sampler; - VkDescriptorImageInfo descriptor; - } offscreenPass{}; - - VulkanExample() : VulkanExampleBase() - { - title = "Conservative rasterization"; - - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -2.0f)); - - // Enable extension required for conservative rasterization - enabledDeviceExtensions.push_back(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME); - - // Reading device properties of conservative rasterization requires VK_KHR_get_physical_device_properties2 to be enabled - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ~VulkanExample() - { - if (device) { - vkDestroyImageView(device, offscreenPass.color.view, nullptr); - vkDestroyImage(device, offscreenPass.color.image, nullptr); - vkFreeMemory(device, offscreenPass.color.mem, nullptr); - vkDestroyImageView(device, offscreenPass.depth.view, nullptr); - vkDestroyImage(device, offscreenPass.depth.image, nullptr); - vkFreeMemory(device, offscreenPass.depth.mem, nullptr); - - vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); - vkDestroySampler(device, offscreenPass.sampler, nullptr); - vkDestroyFramebuffer(device, offscreenPass.frameBuffer, nullptr); - - vkDestroyPipeline(device, pipelines.triangle, nullptr); - vkDestroyPipeline(device, pipelines.triangleOverlay, nullptr); - vkDestroyPipeline(device, pipelines.triangleConservativeRaster, nullptr); - vkDestroyPipeline(device, pipelines.fullscreen, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayouts.fullscreen, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.scene, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.scene, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.fullscreen, nullptr); - - uniformBuffer.destroy(); - triangle.vertices.destroy(); - triangle.indices.destroy(); - } - } - - void getEnabledFeatures() - { - enabledFeatures.fillModeNonSolid = deviceFeatures.fillModeNonSolid; - enabledFeatures.wideLines = deviceFeatures.wideLines; - } - - /* - Setup offscreen framebuffer, attachments and render passes for lower resolution rendering of the scene - */ - void prepareOffscreen() - { - // We "magnify" the offscreen rendered triangle so that the conservative rasterization feature is easier to see - const int32_t magnification = 16; - - offscreenPass.width = width / magnification; - offscreenPass.height = height / magnification; - - const VkFormat fbColorFormat = VK_FORMAT_R8G8B8A8_UNORM; - - // Find a suitable depth format - VkFormat fbDepthFormat; - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat); - assert(validDepthFormat); - - // Color attachment - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = fbColorFormat; - image.extent.width = offscreenPass.width; - image.extent.height = offscreenPass.height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - // We will sample directly from the color attachment - image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.color.image)); - vkGetImageMemoryRequirements(device, offscreenPass.color.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.color.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.color.image, offscreenPass.color.mem, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = fbColorFormat; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = offscreenPass.color.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreenPass.color.view)); - - // Create sampler to sample from the attachment in the fragment shader - VkSamplerCreateInfo samplerInfo = vks::initializers::samplerCreateInfo(); - samplerInfo.magFilter = VK_FILTER_NEAREST; - samplerInfo.minFilter = VK_FILTER_NEAREST; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = samplerInfo.addressModeU; - samplerInfo.addressModeW = samplerInfo.addressModeU; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.maxAnisotropy = 1.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 1.0f; - samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &offscreenPass.sampler)); - - // Depth stencil attachment - image.format = fbDepthFormat; - image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.depth.image)); - vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0)); - - VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo(); - depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilView.format = fbDepthFormat; - depthStencilView.flags = 0; - depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - depthStencilView.subresourceRange.baseMipLevel = 0; - depthStencilView.subresourceRange.levelCount = 1; - depthStencilView.subresourceRange.baseArrayLayer = 0; - depthStencilView.subresourceRange.layerCount = 1; - depthStencilView.image = offscreenPass.depth.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view)); - - // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering - - std::array attchmentDescriptions = {}; - // Color attachment - attchmentDescriptions[0].format = fbColorFormat; - attchmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attchmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // Depth attachment - attchmentDescriptions[1].format = fbDepthFormat; - attchmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - VkAttachmentReference depthReference = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - subpassDescription.pDepthStencilAttachment = &depthReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Create the actual renderpass - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attchmentDescriptions.size()); - renderPassInfo.pAttachments = attchmentDescriptions.data(); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpassDescription; - renderPassInfo.dependencyCount = static_cast(dependencies.size()); - renderPassInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &offscreenPass.renderPass)); - - VkImageView attachments[2]; - attachments[0] = offscreenPass.color.view; - attachments[1] = offscreenPass.depth.view; - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = offscreenPass.renderPass; - fbufCreateInfo.attachmentCount = 2; - fbufCreateInfo.pAttachments = attachments; - fbufCreateInfo.width = offscreenPass.width; - fbufCreateInfo.height = offscreenPass.height; - fbufCreateInfo.layers = 1; - - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreenPass.frameBuffer)); - - // Fill a descriptor for later use in a descriptor set - offscreenPass.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - offscreenPass.descriptor.imageView = offscreenPass.color.view; - offscreenPass.descriptor.sampler = offscreenPass.sampler; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - First render pass: Render a low res triangle to an offscreen framebuffer to use for visualization in second pass - */ - { - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = offscreenPass.renderPass; - renderPassBeginInfo.framebuffer = offscreenPass.frameBuffer; - renderPassBeginInfo.renderArea.extent.width = offscreenPass.width; - renderPassBeginInfo.renderArea.extent.height = offscreenPass.height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - VkViewport viewport = vks::initializers::viewport((float)offscreenPass.width, (float)offscreenPass.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(offscreenPass.width, offscreenPass.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, conservativeRasterEnabled ? pipelines.triangleConservativeRaster : pipelines.triangle); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &triangle.vertices.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], triangle.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdDrawIndexed(drawCmdBuffers[i], triangle.indexCount, 1, 0, 0, 0); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Second render pass: Render scene with conservative rasterization - */ - { - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 0.25f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Low-res triangle from offscreen framebuffer - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.fullscreen); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.fullscreen, 0, 1, &descriptorSets.fullscreen, 0, nullptr); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - // Overlay actual triangle - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &triangle.vertices.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], triangle.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.triangleOverlay); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, nullptr); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - // Create a single triangle - struct Vertex { - float position[3]; - float color[3]; - }; - - std::vector vertexBuffer = { - { { 1.0f, 1.0f, 0.0f }, { 1.0f, 0.0f, 0.0f } }, - { { -1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } }, - { { 0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } } - }; - uint32_t vertexBufferSize = static_cast(vertexBuffer.size()) * sizeof(Vertex); - std::vector indexBuffer = { 0, 1, 2 }; - triangle.indexCount = static_cast(indexBuffer.size()); - uint32_t indexBufferSize = triangle.indexCount * sizeof(uint32_t); - - struct StagingBuffers { - vks::Buffer vertices; - vks::Buffer indices; - } stagingBuffers; - - // Host visible source buffers (staging) - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffers.vertices, - vertexBufferSize, - vertexBuffer.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffers.indices, - indexBufferSize, - indexBuffer.data())); - - // Device local destination buffers - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &triangle.vertices, - vertexBufferSize)); - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &triangle.indices, - indexBufferSize)); - - // Copy from host do device - vulkanDevice->copyBuffer(&stagingBuffers.vertices, &triangle.vertices, queue); - vulkanDevice->copyBuffer(&stagingBuffers.indices, &triangle.indices, queue); - - // Clean up - stagingBuffers.vertices.destroy(); - stagingBuffers.indices.destroy(); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = - vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layouts - std::vector setLayoutBindings; - VkDescriptorSetLayoutCreateInfo descriptorLayout; - - // Scene rendering - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), // Binding 0: Vertex shader uniform buffer - }; - descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.scene)); - - // Fullscreen pass - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0) // Binding 0: Fragment shader image sampler - }; - descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.fullscreen)); - - // Sets - VkDescriptorSetAllocateInfo descriptorSetAllocInfo; - - // Scene rendering - descriptorSetAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.scene, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.scene)); - std::vector offScreenWriteDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(offScreenWriteDescriptorSets.size()), offScreenWriteDescriptorSets.data(), 0, nullptr); - - // Fullscreen pass - descriptorSetAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.fullscreen, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.fullscreen)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.fullscreen, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &offscreenPass.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layouts - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo; - pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.scene, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.scene)); - - pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.fullscreen, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.fullscreen)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE, 0); - - /* - Conservative rasterization setup - */ - - /* - Get device properties for conservative rasterization - Requires VK_KHR_get_physical_device_properties2 and manual function pointer creation - */ - PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR")); - assert(vkGetPhysicalDeviceProperties2KHR); - VkPhysicalDeviceProperties2KHR deviceProps2{}; - conservativeRasterProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT; - deviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; - deviceProps2.pNext = &conservativeRasterProps; - vkGetPhysicalDeviceProperties2KHR(physicalDevice, &deviceProps2); - - // Vertex bindings and attributes - std::vector vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - }; - std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Location 0: Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Location 1: Color - }; - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayouts.fullscreen, renderPass, 0); - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCreateInfo.pRasterizationState = &rasterizationStateCI; - pipelineCreateInfo.pColorBlendState = &colorBlendStateCI; - pipelineCreateInfo.pMultisampleState = &multisampleStateCI; - pipelineCreateInfo.pViewportState = &viewportStateCI; - pipelineCreateInfo.pDepthStencilState = &depthStencilStateCI; - pipelineCreateInfo.pDynamicState = &dynamicStateCI; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - - // Full screen pass - shaderStages[0] = loadShader(getShadersPath() + "conservativeraster/fullscreen.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "conservativeraster/fullscreen.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Empty vertex input state (full screen triangle generated in vertex shader) - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCreateInfo.pVertexInputState = &emptyInputState; - pipelineCreateInfo.layout = pipelineLayouts.fullscreen; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.fullscreen)); - - pipelineCreateInfo.pVertexInputState = &vertexInputState; - pipelineCreateInfo.layout = pipelineLayouts.scene; - - // Original triangle outline - // TODO: Check support for lines - rasterizationStateCI.lineWidth = 2.0f; - rasterizationStateCI.polygonMode = VK_POLYGON_MODE_LINE; - shaderStages[0] = loadShader(getShadersPath() + "conservativeraster/triangle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "conservativeraster/triangleoverlay.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.triangleOverlay)); - - pipelineCreateInfo.renderPass = offscreenPass.renderPass; - - /* - Triangle rendering - */ - rasterizationStateCI.polygonMode = VK_POLYGON_MODE_FILL; - shaderStages[0] = loadShader(getShadersPath() + "conservativeraster/triangle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "conservativeraster/triangle.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - /* - Basic pipeline - */ - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.triangle)); - - /* - Pipeline with conservative rasterization enabled - */ - VkPipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterStateCI{}; - conservativeRasterStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT; - conservativeRasterStateCI.conservativeRasterizationMode = VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT; - conservativeRasterStateCI.extraPrimitiveOverestimationSize = conservativeRasterProps.maxExtraPrimitiveOverestimationSize; - - // Conservative rasterization state has to be chained into the pipeline rasterization state create info structure - rasterizationStateCI.pNext = &conservativeRasterStateCI; - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.triangleConservativeRaster)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffer, - sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - updateUniformBuffersScene(); - } - - void updateUniformBuffersScene() - { - uniformData.projection = camera.matrices.perspective; - uniformData.model = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareOffscreen(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffersScene(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->checkBox("Conservative rasterization", &conservativeRasterEnabled)) { - buildCommandBuffers(); - } - } - if (overlay->header("Device properties")) { - overlay->text("maxExtraPrimitiveOverestimationSize: %f", conservativeRasterProps.maxExtraPrimitiveOverestimationSize); - overlay->text("extraPrimitiveOverestimationSizeGranularity: %f", conservativeRasterProps.extraPrimitiveOverestimationSizeGranularity); - overlay->text("primitiveUnderestimation: %s", conservativeRasterProps.primitiveUnderestimation ? "yes" : "no"); - overlay->text("conservativePointAndLineRasterization: %s", conservativeRasterProps.conservativePointAndLineRasterization ? "yes" : "no"); - overlay->text("degenerateTrianglesRasterized: %s", conservativeRasterProps.degenerateTrianglesRasterized ? "yes" : "no"); - overlay->text("degenerateLinesRasterized: %s", conservativeRasterProps.degenerateLinesRasterized ? "yes" : "no"); - overlay->text("fullyCoveredFragmentShaderInputVariable: %s", conservativeRasterProps.fullyCoveredFragmentShaderInputVariable ? "yes" : "no"); - overlay->text("conservativeRasterizationPostDepthCoverage: %s", conservativeRasterProps.conservativeRasterizationPostDepthCoverage ? "yes" : "no"); - } - - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/debugprintf/debugprintf.cpp b/examples/debugprintf/debugprintf.cpp deleted file mode 100644 index 951337a3..00000000 --- a/examples/debugprintf/debugprintf.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* -* Vulkan Example - Example for using printf in shaders to help debugging. Can be used in conjunction with a debugging app like RenderDoc (https://renderdoc.org) -* -* See this whitepaper for details: https://www.lunarg.com/wp-content/uploads/2021/08/Using-Debug-Printf-02August2021.pdf -* -* Copyright (C) 2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -/* -* The only change required for printf in shaders on the application is enabling the VK_KHR_shader_non_semantic_info extensions -* The actual printing is done in the shaders (see toon.vert from the glsl/hlsl) folder -* For glsl shaders that use this feature, the GL_EXT_debug_printf extension needs to be enabled -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - - -class VulkanExample : public VulkanExampleBase -{ -public: - vks::Buffer uniformBuffer; - vkglTF::Model scene; - - struct UBOVS { - glm::mat4 projection; - glm::mat4 model; - glm::vec4 lightPos = glm::vec4(0.0f, 5.0f, 15.0f, 1.0f); - } uboVS; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Debug output with shader printf"; - camera.setRotation(glm::vec3(-4.35f, 16.25f, 0.0f)); - camera.setRotationSpeed(0.5f); - camera.setPosition(glm::vec3(0.1f, 1.1f, -8.5f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - - // Using printf requires the non semantic info extension to be enabled - enabledDeviceExtensions.push_back(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); - -#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_EXAMPLE_XCODE_GENERATED) - // SRS - Force validation on since shader printf provided by VK_LAYER_KHRONOS_validation on macOS - settings.validation = true; - - // Use layer settings extension to configure Validation Layer - enabledInstanceExtensions.push_back(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME); - - // SRS - Enable the Validation Layer's printf feature - VkLayerSettingEXT layerSetting; - layerSetting.pLayerName = "VK_LAYER_KHRONOS_validation"; - layerSetting.pSettingName = "enables"; - layerSetting.type = VK_LAYER_SETTING_TYPE_STRING_EXT; - layerSetting.valueCount = 1; - - // Make static so layer setting reference remains valid after leaving constructor scope - static const char *layerEnables = "VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT"; - layerSetting.pValues = &layerEnables; - enabledLayerSettings.push_back(layerSetting); - - // SRS - RenderDoc not available on macOS so redirect printf output to stdout - layerSetting.pSettingName = "printf_to_stdout"; - layerSetting.type = VK_LAYER_SETTING_TYPE_BOOL32_EXT; - layerSetting.valueCount = 1; - - // Make static so layer setting reference remains valid after leaving constructor scope - static const VkBool32 layerSettingOn = VK_TRUE; - layerSetting.pValues = &layerSettingOn; - enabledLayerSettings.push_back(layerSetting); - - // Enable required features and set API version for Validation Layer printf - enabledFeatures.fragmentStoresAndAtomics = VK_TRUE; - enabledFeatures.vertexPipelineStoresAndAtomics = VK_TRUE; - - apiVersion = VK_API_VERSION_1_1; -#endif - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - void loadAssets() - { - scene.loadFromFile(getAssetPath() + "models/treasure_smooth.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - VkClearValue clearValues[2]{}; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - scene.draw(drawCmdBuffers[i]); - drawUI(drawCmdBuffers[i]); - vkCmdEndRenderPass(drawCmdBuffers[i]); - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Toon shading pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages = { - loadShader(getShadersPath() + "debugprintf/toon.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "debugprintf/toon.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(uboVS))); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uboVS.projection = camera.matrices.perspective; - uboVS.model = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uboVS, sizeof(uboVS)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Info")) { - overlay->text("Please run this sample with a graphics debugger attached"); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/debugutils/debugutils.cpp b/examples/debugutils/debugutils.cpp deleted file mode 100644 index ab700453..00000000 --- a/examples/debugutils/debugutils.cpp +++ /dev/null @@ -1,775 +0,0 @@ -/* -* Vulkan Example - Example for the VK_EXT_debug_utils extension. Can be used in conjunction with a debugging app like RenderDoc (https://renderdoc.org) -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool wireframe = true; - bool glow = true; - - struct Models { - vkglTF::Model scene, sceneGlow; - } models; - - struct UBOVS { - glm::mat4 projection; - glm::mat4 model; - glm::vec4 lightPos = glm::vec4(0.0f, 5.0f, 15.0f, 1.0f); - } uniformData; - vks::Buffer uniformBuffer; - - struct Pipelines { - VkPipeline toonshading; - VkPipeline color; - VkPipeline wireframe; - VkPipeline postprocess; - } pipelines{}; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - // Framebuffer for offscreen rendering - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory memory; - VkImageView view; - }; - struct OffscreenPass { - int32_t width, height; - VkFramebuffer frameBuffer; - FrameBufferAttachment color, depth; - VkRenderPass renderPass; - VkSampler sampler; - VkDescriptorImageInfo descriptor; - } offscreenPass{}; - - // Function pointers for the VK_EXT_debug_utils_extension - - bool debugUtilsSupported = false; - - PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT{ nullptr }; - PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT{ nullptr }; - PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT{ nullptr }; - PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT{ nullptr }; - PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT{ nullptr }; - PFN_vkQueueBeginDebugUtilsLabelEXT vkQueueBeginDebugUtilsLabelEXT{ nullptr }; - PFN_vkQueueInsertDebugUtilsLabelEXT vkQueueInsertDebugUtilsLabelEXT{ nullptr }; - PFN_vkQueueEndDebugUtilsLabelEXT vkQueueEndDebugUtilsLabelEXT{ nullptr }; - PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT{ nullptr }; - - VulkanExample() : VulkanExampleBase() - { - title = "Debugging with VK_EXT_debug_utils"; - camera.setRotation(glm::vec3(-4.35f, 16.25f, 0.0f)); - camera.setRotationSpeed(0.5f); - camera.setPosition(glm::vec3(0.1f, 1.1f, -8.5f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Fill mode non solid is required for wireframe display - if (deviceFeatures.fillModeNonSolid) { - enabledFeatures.fillModeNonSolid = VK_TRUE; - }; - wireframe = deviceFeatures.fillModeNonSolid; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.toonshading, nullptr); - vkDestroyPipeline(device, pipelines.color, nullptr); - vkDestroyPipeline(device, pipelines.postprocess, nullptr); - if (pipelines.wireframe != VK_NULL_HANDLE) { - vkDestroyPipeline(device, pipelines.wireframe, nullptr); - } - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - uniformBuffer.destroy(); - - // Offscreen - // Color attachment - vkDestroyImageView(device, offscreenPass.color.view, nullptr); - vkDestroyImage(device, offscreenPass.color.image, nullptr); - vkFreeMemory(device, offscreenPass.color.memory, nullptr); - - // Depth attachment - vkDestroyImageView(device, offscreenPass.depth.view, nullptr); - vkDestroyImage(device, offscreenPass.depth.image, nullptr); - vkFreeMemory(device, offscreenPass.depth.memory, nullptr); - - vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); - vkDestroySampler(device, offscreenPass.sampler, nullptr); - vkDestroyFramebuffer(device, offscreenPass.frameBuffer, nullptr); - } - } - - /* - Debug utils functions - */ - - // Checks if debug utils are supported (usually only when a graphics debugger is active) and does the setup necessary to use this debug utils - void setupDebugUtils() - { - // Check if the debug utils extension is present (which is the case if run from a graphics debugger) - bool extensionPresent = false; - uint32_t extensionCount; - vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); - std::vector extensions(extensionCount); - vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); - for (auto& extension : extensions) { - if (strcmp(extension.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) { - extensionPresent = true; - break; - } - } - - if (extensionPresent) { - // As with an other extension, function pointers need to be manually loaded - vkCreateDebugUtilsMessengerEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT")); - vkDestroyDebugUtilsMessengerEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT")); - vkCmdBeginDebugUtilsLabelEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT")); - vkCmdInsertDebugUtilsLabelEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdInsertDebugUtilsLabelEXT")); - vkCmdEndDebugUtilsLabelEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT")); - vkQueueBeginDebugUtilsLabelEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkQueueBeginDebugUtilsLabelEXT")); - vkQueueInsertDebugUtilsLabelEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkQueueInsertDebugUtilsLabelEXT")); - vkQueueEndDebugUtilsLabelEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkQueueEndDebugUtilsLabelEXT")); - vkSetDebugUtilsObjectNameEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT")); - - // Set flag if at least one function pointer is present - debugUtilsSupported = (vkCreateDebugUtilsMessengerEXT != VK_NULL_HANDLE); - } - else { - std::cout << "Warning: " << VK_EXT_DEBUG_UTILS_EXTENSION_NAME << " not present, debug utils are disabled."; - std::cout << "Try running the sample from inside a Vulkan graphics debugger (e.g. RenderDoc)" << std::endl; - } - } - - // The debug utils extensions allows us to put labels into command buffers and queues (to e.g. mark regions of interest) and to name Vulkan objects - // We wrap these into functions for convenience - - // Functions for putting labels into a command buffer - // Labels consist of a name and an optional color - // How or if these are diplayed depends on the debugger used (RenderDoc e.g. displays both) - - void cmdBeginLabel(VkCommandBuffer command_buffer, const char* label_name, std::vector color) - { - if (!debugUtilsSupported) { - return; - } - VkDebugUtilsLabelEXT label = { VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT }; - label.pLabelName = label_name; - memcpy(label.color, color.data(), sizeof(float) * 4); - vkCmdBeginDebugUtilsLabelEXT(command_buffer, &label); - } - - void cmdInsertLabel(VkCommandBuffer command_buffer, const char* label_name, std::vector color) - { - if (!debugUtilsSupported) { - return; - } - VkDebugUtilsLabelEXT label = { VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT }; - label.pLabelName = label_name; - memcpy(label.color, color.data(), sizeof(float) * 4); - vkCmdInsertDebugUtilsLabelEXT(command_buffer, &label); - } - - void cmdEndLabel(VkCommandBuffer command_buffer) - { - if (!debugUtilsSupported) { - return; - } - vkCmdEndDebugUtilsLabelEXT(command_buffer); - } - - // Functions for putting labels into a queue - // Labels consist of a name and an optional color - // How or if these are diplayed depends on the debugger used (RenderDoc e.g. displays both) - - void queueBeginLabel(VkQueue queue, const char* label_name, std::vector color) - { - if (!debugUtilsSupported) { - return; - } - VkDebugUtilsLabelEXT label = { VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT }; - label.pLabelName = label_name; - memcpy(label.color, color.data(), sizeof(float) * 4); - vkQueueBeginDebugUtilsLabelEXT(queue, &label); - } - - void queueInsertLabel(VkQueue queue, const char* label_name, std::vector color) - { - if (!debugUtilsSupported) { - return; - } - VkDebugUtilsLabelEXT label = { VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT }; - label.pLabelName = label_name; - memcpy(label.color, color.data(), sizeof(float) * 4); - vkQueueInsertDebugUtilsLabelEXT(queue, &label); - } - - void queueEndLabel(VkQueue queue) - { - if (!debugUtilsSupported) { - return; - } - vkQueueEndDebugUtilsLabelEXT(queue); - } - - // Function for naming Vulkan objects - // In Vulkan, all objects (that can be named) are opaque unsigned 64 bit handles, and can be cased to uint64_t - - void setObjectName(VkDevice device, VkObjectType object_type, uint64_t object_handle, const char* object_name) - { - if (!debugUtilsSupported) { - return; - } - VkDebugUtilsObjectNameInfoEXT name_info = { VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT }; - name_info.objectType = object_type; - name_info.objectHandle = object_handle; - name_info.pObjectName = object_name; - vkSetDebugUtilsObjectNameEXT(device, &name_info); - } - - // Prepare a texture target and framebuffer for offscreen rendering - void prepareOffscreen() - { - const uint32_t dim = 256; - const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; - - offscreenPass.width = 256; - offscreenPass.height = 256; - - // Find a suitable depth format - VkFormat fbDepthFormat; - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat); - assert(validDepthFormat); - - // Color attachment - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = colorFormat; - image.extent.width = offscreenPass.width; - image.extent.height = offscreenPass.height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - // We will sample directly from the color attachment - image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.color.image)); - vkGetImageMemoryRequirements(device, offscreenPass.color.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.color.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.color.image, offscreenPass.color.memory, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = colorFormat; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = offscreenPass.color.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreenPass.color.view)); - - // Create sampler to sample from the attachment in the fragment shader - VkSamplerCreateInfo samplerInfo = vks::initializers::samplerCreateInfo(); - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = samplerInfo.addressModeU; - samplerInfo.addressModeW = samplerInfo.addressModeU; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.maxAnisotropy = 1.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 1.0f; - samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &offscreenPass.sampler)); - - // Depth stencil attachment - image.format = fbDepthFormat; - image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.depth.image)); - vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.memory, 0)); - - VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo(); - depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilView.format = fbDepthFormat; - depthStencilView.flags = 0; - depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - depthStencilView.subresourceRange.baseMipLevel = 0; - depthStencilView.subresourceRange.levelCount = 1; - depthStencilView.subresourceRange.baseArrayLayer = 0; - depthStencilView.subresourceRange.layerCount = 1; - depthStencilView.image = offscreenPass.depth.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view)); - - // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering - - std::array attchmentDescriptions = {}; - // Color attachment - attchmentDescriptions[0].format = colorFormat; - attchmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attchmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // Depth attachment - attchmentDescriptions[1].format = fbDepthFormat; - attchmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - VkAttachmentReference depthReference = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - subpassDescription.pDepthStencilAttachment = &depthReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Create the actual renderpass - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attchmentDescriptions.size()); - renderPassInfo.pAttachments = attchmentDescriptions.data(); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpassDescription; - renderPassInfo.dependencyCount = static_cast(dependencies.size()); - renderPassInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &offscreenPass.renderPass)); - - VkImageView attachments[2]; - attachments[0] = offscreenPass.color.view; - attachments[1] = offscreenPass.depth.view; - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = offscreenPass.renderPass; - fbufCreateInfo.attachmentCount = 2; - fbufCreateInfo.pAttachments = attachments; - fbufCreateInfo.width = offscreenPass.width; - fbufCreateInfo.height = offscreenPass.height; - fbufCreateInfo.layers = 1; - - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreenPass.frameBuffer)); - - // Fill a descriptor for later use in a descriptor set - offscreenPass.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - offscreenPass.descriptor.imageView = offscreenPass.color.view; - offscreenPass.descriptor.sampler = offscreenPass.sampler; - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.scene.loadFromFile(getAssetPath() + "models/treasure_smooth.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.sceneGlow.loadFromFile(getAssetPath() + "models/treasure_glow.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - // We use a custom draw function so we can insert debug labels with the names of the glTF nodes - void drawModel(vkglTF::Model &model, VkCommandBuffer cmdBuffer) - { - model.bindBuffers(cmdBuffer); - for (auto i = 0; i < model.nodes.size(); i++) - { - // Insert a label for the current model's name - cmdInsertLabel(cmdBuffer, model.nodes[i]->name.c_str(), { 0.0f, 0.0f, 0.0f, 0.0f }); - model.drawNode(model.nodes[i], cmdBuffer); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - VkClearValue clearValues[2]; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - First render pass: Offscreen rendering - */ - if (glow) - { - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = offscreenPass.renderPass; - renderPassBeginInfo.framebuffer = offscreenPass.frameBuffer; - renderPassBeginInfo.renderArea.extent.width = offscreenPass.width; - renderPassBeginInfo.renderArea.extent.height = offscreenPass.height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - cmdBeginLabel(drawCmdBuffers[i], "Off-screen scene rendering", { 1.0f, 0.78f, 0.05f, 1.0f }); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)offscreenPass.width, (float)offscreenPass.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(offscreenPass.width, offscreenPass.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.color); - - drawModel(models.sceneGlow, drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - cmdEndLabel(drawCmdBuffers[i]); - } - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Second render pass: Scene rendering with applied bloom - */ - { - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - cmdBeginLabel(drawCmdBuffers[i], "Render scene", { 0.5f, 0.76f, 0.34f, 1.0f }); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(wireframe ? width / 2 : width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - // Solid rendering - - cmdBeginLabel(drawCmdBuffers[i], "Toon shading draw", { 0.78f, 0.74f, 0.9f, 1.0f }); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.toonshading); - drawModel(models.scene, drawCmdBuffers[i]); - - cmdEndLabel(drawCmdBuffers[i]); - - // Wireframe rendering - if (wireframe) - { - cmdBeginLabel(drawCmdBuffers[i], "Wireframe draw", { 0.53f, 0.78f, 0.91f, 1.0f }); - - scissor.offset.x = width / 2; - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.wireframe); - drawModel(models.scene, drawCmdBuffers[i]); - - cmdEndLabel(drawCmdBuffers[i]); - - scissor.offset.x = 0; - scissor.extent.width = width; - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - } - - // Post processing - if (glow) - { - cmdBeginLabel(drawCmdBuffers[i], "Apply post processing", { 0.93f, 0.89f, 0.69f, 1.0f }); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.postprocess); - // Full screen quad is generated by the vertex shaders, so we reuse four vertices (for four invocations) from current vertex buffer - vkCmdDraw(drawCmdBuffers[i], 4, 1, 0, 0); - - cmdEndLabel(drawCmdBuffers[i]); - } - - cmdBeginLabel(drawCmdBuffers[i], "UI overlay", { 0.23f, 0.65f, 0.28f, 1.0f }); - drawUI(drawCmdBuffers[i]); - cmdEndLabel(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - cmdEndLabel(drawCmdBuffers[i]); - - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader combined sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Color map - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &offscreenPass.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color}); - - // Toon shading pipeline - shaderStages[0] = loadShader(getShadersPath() + "debugutils/toon.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "debugutils/toon.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.toonshading)); - - // Color only pipeline - shaderStages[0] = loadShader(getShadersPath() + "debugutils/colorpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "debugutils/colorpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - pipelineCI.renderPass = offscreenPass.renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.color)); - - // Wire frame rendering pipeline - if (deviceFeatures.fillModeNonSolid) - { - rasterizationStateCI.polygonMode = VK_POLYGON_MODE_LINE; - pipelineCI.renderPass = renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); - } - - // Post processing effect - shaderStages[0] = loadShader(getShadersPath() + "debugutils/postprocess.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "debugutils/postprocess.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - depthStencilStateCI.depthTestEnable = VK_FALSE; - depthStencilStateCI.depthWriteEnable = VK_FALSE; - rasterizationStateCI.polygonMode = VK_POLYGON_MODE_FILL; - rasterizationStateCI.cullMode = VK_CULL_MODE_NONE; - blendAttachmentState.colorWriteMask = 0xF; - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.postprocess)); - } - - // For convencience we name our Vulkan objects in a single place - void nameDebugObjects() - { - // Name some objects for debugging - setObjectName(device, VK_OBJECT_TYPE_IMAGE, (uint64_t)offscreenPass.color.image, "Off-screen color framebuffer"); - setObjectName(device, VK_OBJECT_TYPE_IMAGE, (uint64_t)offscreenPass.depth.image, "Off-screen depth framebuffer"); - setObjectName(device, VK_OBJECT_TYPE_SAMPLER, (uint64_t)offscreenPass.sampler, "Off-screen framebuffer default sampler"); - - setObjectName(device, VK_OBJECT_TYPE_BUFFER, (uint64_t)uniformBuffer.buffer, "Scene uniform buffer block"); - setObjectName(device, VK_OBJECT_TYPE_BUFFER, (uint64_t)models.scene.vertices.buffer, "Scene vertex buffer"); - setObjectName(device, VK_OBJECT_TYPE_BUFFER, (uint64_t)models.scene.indices.buffer, "Scene index buffer"); - setObjectName(device, VK_OBJECT_TYPE_BUFFER, (uint64_t)models.sceneGlow.vertices.buffer, "Glow vertex buffer"); - setObjectName(device, VK_OBJECT_TYPE_BUFFER, (uint64_t)models.sceneGlow.indices.buffer, "Glow index buffer"); - - // Shader module count starts at 2 when UI overlay in base class is enabled - uint32_t moduleIndex = settings.overlay ? 2 : 0; - setObjectName(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)shaderModules[moduleIndex + 0], "Toon shading vertex shader"); - setObjectName(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)shaderModules[moduleIndex + 1], "Toon shading fragment shader"); - setObjectName(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)shaderModules[moduleIndex + 2], "Color-only vertex shader"); - setObjectName(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)shaderModules[moduleIndex + 3], "Color-only fragment shader"); - setObjectName(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)shaderModules[moduleIndex + 4], "Postprocess vertex shader"); - setObjectName(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)shaderModules[moduleIndex + 5], "Postprocess fragment shader"); - - setObjectName(device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)pipelineLayout, "Shared pipeline layout"); - setObjectName(device, VK_OBJECT_TYPE_PIPELINE, (uint64_t)pipelines.toonshading, "Toon shading pipeline"); - setObjectName(device, VK_OBJECT_TYPE_PIPELINE, (uint64_t)pipelines.color, "Color only pipeline"); - if (deviceFeatures.fillModeNonSolid) { - setObjectName(device, VK_OBJECT_TYPE_PIPELINE, (uint64_t)pipelines.wireframe, "Wireframe rendering pipeline"); - } - setObjectName(device, VK_OBJECT_TYPE_PIPELINE, (uint64_t)pipelines.postprocess, "Post processing pipeline"); - - setObjectName(device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)descriptorSetLayout, "Shared descriptor set layout"); - setObjectName(device, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)descriptorSet, "Shared descriptor set"); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffer, - sizeof(uniformData))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.model = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void draw() - { - queueBeginLabel(queue, "Graphics queue command buffer submission", { 1.0f, 1.0f, 1.0f, 1.0f }); - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - queueEndLabel(queue); - } - - void prepare() - { - VulkanExampleBase::prepare(); - setupDebugUtils(); - loadAssets(); - prepareOffscreen(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - nameDebugObjects(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Info")) { - overlay->text("VK_EXT_debug_utils %s", (debugUtilsSupported? "supported" : "not supported")); - } - if (overlay->header("Settings")) { - if (overlay->checkBox("Glow", &glow)) { - buildCommandBuffers(); - } - if (deviceFeatures.fillModeNonSolid) { - if (overlay->checkBox("Wireframe", &wireframe)) { - buildCommandBuffers(); - } - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/deferred/deferred.cpp b/examples/deferred/deferred.cpp deleted file mode 100644 index 379d56f4..00000000 --- a/examples/deferred/deferred.cpp +++ /dev/null @@ -1,804 +0,0 @@ -/* -* Vulkan Example - Deferred shading with multiple render targets (aka G-Buffer) example -* -* This samples shows how to do deferred rendering. Unlike forward rendering, different components like -* albedo, normals, world positions are rendered to offscreen images which are then put together and lit -* in a composition pass -* Use the dropdown in the ui to switch between the final composition pass or the separate components -* -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - int32_t debugDisplayTarget = 0; - - struct { - struct { - vks::Texture2D colorMap; - vks::Texture2D normalMap; - } model; - struct { - vks::Texture2D colorMap; - vks::Texture2D normalMap; - } floor; - } textures; - - struct { - vkglTF::Model model; - vkglTF::Model floor; - } models; - - struct UniformDataOffscreen { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - glm::vec4 instancePos[3]; - } uniformDataOffscreen; - - struct Light { - glm::vec4 position; - glm::vec3 color; - float radius; - }; - - struct UniformDataComposition { - Light lights[6]; - glm::vec4 viewPos; - int debugDisplayTarget = 0; - } uniformDataComposition; - - struct { - vks::Buffer offscreen; - vks::Buffer composition; - } uniformBuffers; - - struct { - VkPipeline offscreen{ VK_NULL_HANDLE }; - VkPipeline composition{ VK_NULL_HANDLE }; - } pipelines; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - - struct { - VkDescriptorSet model{ VK_NULL_HANDLE }; - VkDescriptorSet floor{ VK_NULL_HANDLE }; - VkDescriptorSet composition{ VK_NULL_HANDLE }; - } descriptorSets; - - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - // Framebuffers holding the deferred attachments - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory mem; - VkImageView view; - VkFormat format; - }; - struct FrameBuffer { - int32_t width, height; - VkFramebuffer frameBuffer; - // One attachment for every component required for a deferred rendering setup - FrameBufferAttachment position, normal, albedo; - FrameBufferAttachment depth; - VkRenderPass renderPass; - } offScreenFrameBuf{}; - - // One sampler for the frame buffer color attachments - VkSampler colorSampler{ VK_NULL_HANDLE }; - - VkCommandBuffer offScreenCmdBuffer{ VK_NULL_HANDLE }; - - // Semaphore used to synchronize between offscreen and final scene rendering - VkSemaphore offscreenSemaphore{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Deferred shading"; - camera.type = Camera::CameraType::firstperson; - camera.movementSpeed = 5.0f; -#ifndef __ANDROID__ - camera.rotationSpeed = 0.25f; -#endif - camera.position = { 2.15f, 0.3f, -8.75f }; - camera.setRotation(glm::vec3(-0.75f, 12.5f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroySampler(device, colorSampler, nullptr); - - // Frame buffer - - // Color attachments - vkDestroyImageView(device, offScreenFrameBuf.position.view, nullptr); - vkDestroyImage(device, offScreenFrameBuf.position.image, nullptr); - vkFreeMemory(device, offScreenFrameBuf.position.mem, nullptr); - - vkDestroyImageView(device, offScreenFrameBuf.normal.view, nullptr); - vkDestroyImage(device, offScreenFrameBuf.normal.image, nullptr); - vkFreeMemory(device, offScreenFrameBuf.normal.mem, nullptr); - - vkDestroyImageView(device, offScreenFrameBuf.albedo.view, nullptr); - vkDestroyImage(device, offScreenFrameBuf.albedo.image, nullptr); - vkFreeMemory(device, offScreenFrameBuf.albedo.mem, nullptr); - - // Depth attachment - vkDestroyImageView(device, offScreenFrameBuf.depth.view, nullptr); - vkDestroyImage(device, offScreenFrameBuf.depth.image, nullptr); - vkFreeMemory(device, offScreenFrameBuf.depth.mem, nullptr); - - vkDestroyFramebuffer(device, offScreenFrameBuf.frameBuffer, nullptr); - - vkDestroyPipeline(device, pipelines.composition, nullptr); - vkDestroyPipeline(device, pipelines.offscreen, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - // Uniform buffers - uniformBuffers.offscreen.destroy(); - uniformBuffers.composition.destroy(); - - vkDestroyRenderPass(device, offScreenFrameBuf.renderPass, nullptr); - - textures.model.colorMap.destroy(); - textures.model.normalMap.destroy(); - textures.floor.colorMap.destroy(); - textures.floor.normalMap.destroy(); - - vkDestroySemaphore(device, offscreenSemaphore, nullptr); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - }; - - // Create a frame buffer attachment - void createAttachment( - VkFormat format, - VkImageUsageFlagBits usage, - FrameBufferAttachment *attachment) - { - VkImageAspectFlags aspectMask = 0; - VkImageLayout imageLayout; - - attachment->format = format; - - if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) - { - aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } - if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) - { - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (format >= VK_FORMAT_D16_UNORM_S8_UINT) - aspectMask |=VK_IMAGE_ASPECT_STENCIL_BIT; - imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } - - assert(aspectMask > 0); - - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = format; - image.extent.width = offScreenFrameBuf.width; - image.extent.height = offScreenFrameBuf.height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.usage = usage | VK_IMAGE_USAGE_SAMPLED_BIT; - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &attachment->image)); - vkGetImageMemoryRequirements(device, attachment->image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &attachment->mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, attachment->image, attachment->mem, 0)); - - VkImageViewCreateInfo imageView = vks::initializers::imageViewCreateInfo(); - imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageView.format = format; - imageView.subresourceRange = {}; - imageView.subresourceRange.aspectMask = aspectMask; - imageView.subresourceRange.baseMipLevel = 0; - imageView.subresourceRange.levelCount = 1; - imageView.subresourceRange.baseArrayLayer = 0; - imageView.subresourceRange.layerCount = 1; - imageView.image = attachment->image; - VK_CHECK_RESULT(vkCreateImageView(device, &imageView, nullptr, &attachment->view)); - } - - // Prepare a new framebuffer and attachments for offscreen rendering (G-Buffer) - void prepareOffscreenFramebuffer() - { - // Note: Instead of using fixed sizes, one could also match the window size and recreate the attachments on resize - offScreenFrameBuf.width = 2048; - offScreenFrameBuf.height = 2048; - - // Color attachments - - // (World space) Positions - createAttachment( - VK_FORMAT_R16G16B16A16_SFLOAT, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - &offScreenFrameBuf.position); - - // (World space) Normals - createAttachment( - VK_FORMAT_R16G16B16A16_SFLOAT, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - &offScreenFrameBuf.normal); - - // Albedo (color) - createAttachment( - VK_FORMAT_R8G8B8A8_UNORM, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - &offScreenFrameBuf.albedo); - - // Depth attachment - - // Find a suitable depth format - VkFormat attDepthFormat; - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attDepthFormat); - assert(validDepthFormat); - - createAttachment( - attDepthFormat, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - &offScreenFrameBuf.depth); - - // Set up separate renderpass with references to the color and depth attachments - std::array attachmentDescs = {}; - - // Init attachment properties - for (uint32_t i = 0; i < 4; ++i) - { - attachmentDescs[i].samples = VK_SAMPLE_COUNT_1_BIT; - attachmentDescs[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachmentDescs[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachmentDescs[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachmentDescs[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - if (i == 3) - { - attachmentDescs[i].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachmentDescs[i].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } - else - { - attachmentDescs[i].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachmentDescs[i].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - } - - // Formats - attachmentDescs[0].format = offScreenFrameBuf.position.format; - attachmentDescs[1].format = offScreenFrameBuf.normal.format; - attachmentDescs[2].format = offScreenFrameBuf.albedo.format; - attachmentDescs[3].format = offScreenFrameBuf.depth.format; - - std::vector colorReferences; - colorReferences.push_back({ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); - colorReferences.push_back({ 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); - colorReferences.push_back({ 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); - - VkAttachmentReference depthReference = {}; - depthReference.attachment = 3; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.pColorAttachments = colorReferences.data(); - subpass.colorAttachmentCount = static_cast(colorReferences.size()); - subpass.pDepthStencilAttachment = &depthReference; - - // Use subpass dependencies for attachment layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.pAttachments = attachmentDescs.data(); - renderPassInfo.attachmentCount = static_cast(attachmentDescs.size()); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 2; - renderPassInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &offScreenFrameBuf.renderPass)); - - std::array attachments; - attachments[0] = offScreenFrameBuf.position.view; - attachments[1] = offScreenFrameBuf.normal.view; - attachments[2] = offScreenFrameBuf.albedo.view; - attachments[3] = offScreenFrameBuf.depth.view; - - VkFramebufferCreateInfo fbufCreateInfo = {}; - fbufCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fbufCreateInfo.pNext = NULL; - fbufCreateInfo.renderPass = offScreenFrameBuf.renderPass; - fbufCreateInfo.pAttachments = attachments.data(); - fbufCreateInfo.attachmentCount = static_cast(attachments.size()); - fbufCreateInfo.width = offScreenFrameBuf.width; - fbufCreateInfo.height = offScreenFrameBuf.height; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offScreenFrameBuf.frameBuffer)); - - // Create sampler to sample from the color attachments - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_NEAREST; - sampler.minFilter = VK_FILTER_NEAREST; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 1.0f; - sampler.minLod = 0.0f; - sampler.maxLod = 1.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &colorSampler)); - } - - // Build command buffer for rendering the scene to the offscreen frame buffer attachments - void buildDeferredCommandBuffer() - { - if (offScreenCmdBuffer == VK_NULL_HANDLE) { - offScreenCmdBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false); - } - - // Create a semaphore used to synchronize offscreen rendering and usage - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &offscreenSemaphore)); - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - // Clear values for all attachments written in the fragment shader - std::array clearValues; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[2].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[3].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = offScreenFrameBuf.renderPass; - renderPassBeginInfo.framebuffer = offScreenFrameBuf.frameBuffer; - renderPassBeginInfo.renderArea.extent.width = offScreenFrameBuf.width; - renderPassBeginInfo.renderArea.extent.height = offScreenFrameBuf.height; - renderPassBeginInfo.clearValueCount = static_cast(clearValues.size()); - renderPassBeginInfo.pClearValues = clearValues.data(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(offScreenCmdBuffer, &cmdBufInfo)); - - vkCmdBeginRenderPass(offScreenCmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)offScreenFrameBuf.width, (float)offScreenFrameBuf.height, 0.0f, 1.0f); - vkCmdSetViewport(offScreenCmdBuffer, 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(offScreenFrameBuf.width, offScreenFrameBuf.height, 0, 0); - vkCmdSetScissor(offScreenCmdBuffer, 0, 1, &scissor); - - vkCmdBindPipeline(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.offscreen); - - // Floor - vkCmdBindDescriptorSets(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.floor, 0, nullptr); - models.floor.draw(offScreenCmdBuffer); - - // We render multiple instances of a model - vkCmdBindDescriptorSets(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.model, 0, nullptr); - models.model.bindBuffers(offScreenCmdBuffer); - vkCmdDrawIndexed(offScreenCmdBuffer, models.model.indices.count, 3, 0, 0, 0); - - vkCmdEndRenderPass(offScreenCmdBuffer); - - VK_CHECK_RESULT(vkEndCommandBuffer(offScreenCmdBuffer)); - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.model.loadFromFile(getAssetPath() + "models/armor/armor.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.floor.loadFromFile(getAssetPath() + "models/deferred_floor.gltf", vulkanDevice, queue, glTFLoadingFlags); - textures.model.colorMap.loadFromFile(getAssetPath() + "models/armor/colormap_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.model.normalMap.loadFromFile(getAssetPath() + "models/armor/normalmap_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.floor.colorMap.loadFromFile(getAssetPath() + "textures/stonefloor01_color_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.floor.normalMap.loadFromFile(getAssetPath() + "textures/stonefloor01_normal_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.composition, 0, nullptr); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.composition); - - // Final composition - // This is done by simply drawing a full screen quad - // The fragment shader then combines the deferred attachments into the final image - // Note: Also used for debug display if debugDisplayTarget > 0 - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 8), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 9) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layouts - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Position texture target / Scene colormap - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 2 : Normals texture target - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - // Binding 3 : Albedo texture target - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), - // Binding 4 : Fragment shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 4), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - std::vector writeDescriptorSets; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - // Image descriptors for the offscreen color attachments - VkDescriptorImageInfo texDescriptorPosition = - vks::initializers::descriptorImageInfo( - colorSampler, - offScreenFrameBuf.position.view, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - VkDescriptorImageInfo texDescriptorNormal = - vks::initializers::descriptorImageInfo( - colorSampler, - offScreenFrameBuf.normal.view, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - VkDescriptorImageInfo texDescriptorAlbedo = - vks::initializers::descriptorImageInfo( - colorSampler, - offScreenFrameBuf.albedo.view, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Deferred composition - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.composition)); - writeDescriptorSets = { - // Binding 1 : Position texture target - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &texDescriptorPosition), - // Binding 2 : Normals texture target - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &texDescriptorNormal), - // Binding 3 : Albedo texture target - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &texDescriptorAlbedo), - // Binding 4 : Fragment shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4, &uniformBuffers.composition.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Offscreen (scene) - - // Model - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.model)); - writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.model, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.offscreen.descriptor), - // Binding 1: Color map - vks::initializers::writeDescriptorSet(descriptorSets.model, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.model.colorMap.descriptor), - // Binding 2: Normal map - vks::initializers::writeDescriptorSet(descriptorSets.model, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.model.normalMap.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Background - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.floor)); - writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.floor, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.offscreen.descriptor), - // Binding 1: Color map - vks::initializers::writeDescriptorSet(descriptorSets.floor, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.floor.colorMap.descriptor), - // Binding 2: Normal map - vks::initializers::writeDescriptorSet(descriptorSets.floor, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.floor.normalMap.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Pipeline layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Final fullscreen composition pass pipeline - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - shaderStages[0] = loadShader(getShadersPath() + "deferred/deferred.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "deferred/deferred.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Empty vertex input state, vertices are generated by the vertex shader - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCI.pVertexInputState = &emptyInputState; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.composition)); - - // Vertex input state from glTF model for pipeline rendering models - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Tangent}); - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - - // Offscreen pipeline - shaderStages[0] = loadShader(getShadersPath() + "deferred/mrt.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "deferred/mrt.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - // Separate render pass - pipelineCI.renderPass = offScreenFrameBuf.renderPass; - - // Blend attachment states required for all color attachments - // This is important, as color write mask will otherwise be 0x0 and you - // won't see anything rendered to the attachment - std::array blendAttachmentStates = { - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE) - }; - - colorBlendState.attachmentCount = static_cast(blendAttachmentStates.size()); - colorBlendState.pAttachments = blendAttachmentStates.data(); - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.offscreen)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Offscreen vertex shader - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.offscreen, sizeof(UniformDataOffscreen))); - - // Deferred fragment shader - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.composition, sizeof(UniformDataComposition))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffers.offscreen.map()); - VK_CHECK_RESULT(uniformBuffers.composition.map()); - - // Setup instanced model positions - uniformDataOffscreen.instancePos[0] = glm::vec4(0.0f); - uniformDataOffscreen.instancePos[1] = glm::vec4(-4.0f, 0.0, -4.0f, 0.0f); - uniformDataOffscreen.instancePos[2] = glm::vec4(4.0f, 0.0, -4.0f, 0.0f); - - // Update - updateUniformBufferOffscreen(); - updateUniformBufferComposition(); - } - - // Update matrices used for the offscreen rendering of the scene - void updateUniformBufferOffscreen() - { - uniformDataOffscreen.projection = camera.matrices.perspective; - uniformDataOffscreen.view = camera.matrices.view; - uniformDataOffscreen.model = glm::mat4(1.0f); - memcpy(uniformBuffers.offscreen.mapped, &uniformDataOffscreen, sizeof(UniformDataOffscreen)); - } - - // Update lights and parameters passed to the composition shaders - void updateUniformBufferComposition() - { - // White - uniformDataComposition.lights[0].position = glm::vec4(0.0f, 0.0f, 1.0f, 0.0f); - uniformDataComposition.lights[0].color = glm::vec3(1.5f); - uniformDataComposition.lights[0].radius = 15.0f * 0.25f; - // Red - uniformDataComposition.lights[1].position = glm::vec4(-2.0f, 0.0f, 0.0f, 0.0f); - uniformDataComposition.lights[1].color = glm::vec3(1.0f, 0.0f, 0.0f); - uniformDataComposition.lights[1].radius = 15.0f; - // Blue - uniformDataComposition.lights[2].position = glm::vec4(2.0f, -1.0f, 0.0f, 0.0f); - uniformDataComposition.lights[2].color = glm::vec3(0.0f, 0.0f, 2.5f); - uniformDataComposition.lights[2].radius = 5.0f; - // Yellow - uniformDataComposition.lights[3].position = glm::vec4(0.0f, -0.9f, 0.5f, 0.0f); - uniformDataComposition.lights[3].color = glm::vec3(1.0f, 1.0f, 0.0f); - uniformDataComposition.lights[3].radius = 2.0f; - // Green - uniformDataComposition.lights[4].position = glm::vec4(0.0f, -0.5f, 0.0f, 0.0f); - uniformDataComposition.lights[4].color = glm::vec3(0.0f, 1.0f, 0.2f); - uniformDataComposition.lights[4].radius = 5.0f; - // Yellow - uniformDataComposition.lights[5].position = glm::vec4(0.0f, -1.0f, 0.0f, 0.0f); - uniformDataComposition.lights[5].color = glm::vec3(1.0f, 0.7f, 0.3f); - uniformDataComposition.lights[5].radius = 25.0f; - - // Animate the lights - if (!paused) { - uniformDataComposition.lights[0].position.x = sin(glm::radians(360.0f * timer)) * 5.0f; - uniformDataComposition.lights[0].position.z = cos(glm::radians(360.0f * timer)) * 5.0f; - - uniformDataComposition.lights[1].position.x = -4.0f + sin(glm::radians(360.0f * timer) + 45.0f) * 2.0f; - uniformDataComposition.lights[1].position.z = 0.0f + cos(glm::radians(360.0f * timer) + 45.0f) * 2.0f; - - uniformDataComposition.lights[2].position.x = 4.0f + sin(glm::radians(360.0f * timer)) * 2.0f; - uniformDataComposition.lights[2].position.z = 0.0f + cos(glm::radians(360.0f * timer)) * 2.0f; - - uniformDataComposition.lights[4].position.x = 0.0f + sin(glm::radians(360.0f * timer + 90.0f)) * 5.0f; - uniformDataComposition.lights[4].position.z = 0.0f - cos(glm::radians(360.0f * timer + 45.0f)) * 5.0f; - - uniformDataComposition.lights[5].position.x = 0.0f + sin(glm::radians(-360.0f * timer + 135.0f)) * 10.0f; - uniformDataComposition.lights[5].position.z = 0.0f - cos(glm::radians(-360.0f * timer - 45.0f)) * 10.0f; - } - - // Current view position - uniformDataComposition.viewPos = glm::vec4(camera.position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f); - - uniformDataComposition.debugDisplayTarget = debugDisplayTarget; - - memcpy(uniformBuffers.composition.mapped, &uniformDataComposition, sizeof(UniformDataComposition)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareOffscreenFramebuffer(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - buildDeferredCommandBuffer(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - - // The scene render command buffer has to wait for the offscreen - // rendering to be finished before we can use the framebuffer - // color image for sampling during final rendering - // To ensure this we use a dedicated offscreen synchronization - // semaphore that will be signaled when offscreen rendering - // has been finished - // This is necessary as an implementation may start both - // command buffers at the same time, there is no guarantee - // that command buffers will be executed in the order they - // have been submitted by the application - - // Offscreen rendering - - // Wait for swap chain presentation to finish - submitInfo.pWaitSemaphores = &semaphores.presentComplete; - // Signal ready with offscreen semaphore - submitInfo.pSignalSemaphores = &offscreenSemaphore; - - // Submit work - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &offScreenCmdBuffer; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - // Scene rendering - - // Wait for offscreen semaphore - submitInfo.pWaitSemaphores = &offscreenSemaphore; - // Signal ready with render complete semaphore - submitInfo.pSignalSemaphores = &semaphores.renderComplete; - - // Submit work - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBufferComposition(); - updateUniformBufferOffscreen(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->comboBox("Display", &debugDisplayTarget, { "Final composition", "Position", "Normals", "Albedo", "Specular" }); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/deferredmultisampling/deferredmultisampling.cpp b/examples/deferredmultisampling/deferredmultisampling.cpp deleted file mode 100644 index 02dbe78e..00000000 --- a/examples/deferredmultisampling/deferredmultisampling.cpp +++ /dev/null @@ -1,638 +0,0 @@ -/* -* Vulkan Example - Multi sampling with explicit resolve for deferred shading example -* -* This sample adds hardware accelerated multi sampling to the deferred rendering sample -* -* Copyright (C) 2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanFrameBuffer.hpp" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - int32_t debugDisplayTarget = 0; - bool useMSAA = true; - bool useSampleShading = true; - VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; - - struct { - struct { - vks::Texture2D colorMap; - vks::Texture2D normalMap; - } model; - struct { - vks::Texture2D colorMap; - vks::Texture2D normalMap; - } background; - } textures; - - struct { - vkglTF::Model model; - vkglTF::Model background; - } models; - - struct UniformDataOffscreen { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - glm::vec4 instancePos[3]; - } uniformDataOffscreen; - - struct Light { - glm::vec4 position; - glm::vec3 color; - float radius; - }; - - struct UniformDataComposition { - Light lights[6]; - glm::vec4 viewPos; - int32_t debugDisplayTarget = 0; - } uniformDataComposition; - - struct { - vks::Buffer offscreen; - vks::Buffer composition; - } uniformBuffers; - - struct { - VkPipeline deferred{ VK_NULL_HANDLE }; // Deferred lighting calculation - VkPipeline deferredNoMSAA{ VK_NULL_HANDLE }; // Deferred lighting calculation with explicit MSAA resolve - VkPipeline offscreen{ VK_NULL_HANDLE }; // (Offscreen) scene rendering (fill G-Buffers) - VkPipeline offscreenSampleShading{ VK_NULL_HANDLE }; // (Offscreen) scene rendering (fill G-Buffers) with sample shading rate enabled - } pipelines; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - - struct { - VkDescriptorSet model{ VK_NULL_HANDLE }; - VkDescriptorSet background{ VK_NULL_HANDLE }; - VkDescriptorSet composition{ VK_NULL_HANDLE }; - } descriptorSets; - - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - vks::Framebuffer* offscreenframeBuffers{}; - - VkCommandBuffer offScreenCmdBuffer{ VK_NULL_HANDLE }; - - // Semaphore used to synchronize between offscreen and final scene rendering - VkSemaphore offscreenSemaphore{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Multi sampled deferred shading"; - camera.type = Camera::CameraType::firstperson; - camera.movementSpeed = 5.0f; -#ifndef __ANDROID__ - camera.rotationSpeed = 0.25f; -#endif - camera.position = { 2.15f, 0.3f, -8.75f }; - camera.setRotation(glm::vec3(-0.75f, 12.5f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - // Frame buffers - if (offscreenframeBuffers) { - delete offscreenframeBuffers; - } - - vkDestroyPipeline(device, pipelines.deferred, nullptr); - vkDestroyPipeline(device, pipelines.deferredNoMSAA, nullptr); - vkDestroyPipeline(device, pipelines.offscreen, nullptr); - vkDestroyPipeline(device, pipelines.offscreenSampleShading, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - // Uniform buffers - uniformBuffers.offscreen.destroy(); - uniformBuffers.composition.destroy(); - - textures.model.colorMap.destroy(); - textures.model.normalMap.destroy(); - textures.background.colorMap.destroy(); - textures.background.normalMap.destroy(); - - vkDestroySemaphore(device, offscreenSemaphore, nullptr); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Enable sample rate shading filtering if supported - if (deviceFeatures.sampleRateShading) { - enabledFeatures.sampleRateShading = VK_TRUE; - } - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - }; - - // Prepare the framebuffer for offscreen rendering with multiple attachments used as render targets inside the fragment shaders - void deferredSetup() - { - offscreenframeBuffers = new vks::Framebuffer(vulkanDevice); - -#if defined(__ANDROID__) - // Use max. screen dimension as deferred framebuffer size - offscreenframeBuffers->width = std::max(width, height); - offscreenframeBuffers->height = std::max(width, height); -#else - offscreenframeBuffers->width = 2048; - offscreenframeBuffers->height = 2048; -#endif - - // Four attachments (3 color, 1 depth) - vks::AttachmentCreateInfo attachmentInfo = {}; - attachmentInfo.width = offscreenframeBuffers->width; - attachmentInfo.height = offscreenframeBuffers->height; - attachmentInfo.layerCount = 1; - attachmentInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - attachmentInfo.imageSampleCount = sampleCount; - - // Color attachments - // Attachment 0: (World space) Positions - attachmentInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT; - offscreenframeBuffers->addAttachment(attachmentInfo); - - // Attachment 1: (World space) Normals - attachmentInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT; - offscreenframeBuffers->addAttachment(attachmentInfo); - - // Attachment 2: Albedo (color) - attachmentInfo.format = VK_FORMAT_R8G8B8A8_UNORM; - offscreenframeBuffers->addAttachment(attachmentInfo); - - // Depth attachment - // Find a suitable depth format - VkFormat attDepthFormat; - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attDepthFormat); - assert(validDepthFormat); - - attachmentInfo.format = attDepthFormat; - attachmentInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - offscreenframeBuffers->addAttachment(attachmentInfo); - - // Create sampler to sample from the color attachments - VK_CHECK_RESULT(offscreenframeBuffers->createSampler(VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)); - - // Create default renderpass for the framebuffer - VK_CHECK_RESULT(offscreenframeBuffers->createRenderPass()); - } - - // Build command buffer for rendering the scene to the offscreen frame buffer attachments - void buildDeferredCommandBuffer() - { - if (offScreenCmdBuffer == VK_NULL_HANDLE) { - offScreenCmdBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false); - } - - // Create a semaphore used to synchronize offscreen rendering and usage - if (offscreenSemaphore == VK_NULL_HANDLE) { - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &offscreenSemaphore)); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - // Clear values for all attachments written in the fragment shader - std::array clearValues; - clearValues[0].color = clearValues[1].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[2].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[3].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = offscreenframeBuffers->renderPass; - renderPassBeginInfo.framebuffer = offscreenframeBuffers->framebuffer; - renderPassBeginInfo.renderArea.extent.width = offscreenframeBuffers->width; - renderPassBeginInfo.renderArea.extent.height = offscreenframeBuffers->height; - renderPassBeginInfo.clearValueCount = static_cast(clearValues.size()); - renderPassBeginInfo.pClearValues = clearValues.data(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(offScreenCmdBuffer, &cmdBufInfo)); - - vkCmdBeginRenderPass(offScreenCmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)offscreenframeBuffers->width, (float)offscreenframeBuffers->height, 0.0f, 1.0f); - vkCmdSetViewport(offScreenCmdBuffer, 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(offscreenframeBuffers->width, offscreenframeBuffers->height, 0, 0); - vkCmdSetScissor(offScreenCmdBuffer, 0, 1, &scissor); - - vkCmdBindPipeline(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, useSampleShading ? pipelines.offscreenSampleShading : pipelines.offscreen); - - // Background - vkCmdBindDescriptorSets(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.background, 0, nullptr); - models.background.draw(offScreenCmdBuffer); - - // Object - vkCmdBindDescriptorSets(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.model, 0, nullptr); - models.model.bindBuffers(offScreenCmdBuffer); - vkCmdDrawIndexed(offScreenCmdBuffer, models.model.indices.count, 3, 0, 0, 0); - - vkCmdEndRenderPass(offScreenCmdBuffer); - - VK_CHECK_RESULT(vkEndCommandBuffer(offScreenCmdBuffer)); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = VulkanExampleBase::frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.composition, 0, nullptr); - - // Final composition as full screen quad - // Note: Also used for debug display if debugDisplayTarget > 0 - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, useMSAA ? pipelines.deferred : pipelines.deferredNoMSAA); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.model.loadFromFile(getAssetPath() + "models/armor/armor.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.background.loadFromFile(getAssetPath() + "models/deferred_box.gltf", vulkanDevice, queue, glTFLoadingFlags); - textures.model.colorMap.loadFromFile(getAssetPath() + "models/armor/colormap_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.model.normalMap.loadFromFile(getAssetPath() + "models/armor/normalmap_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.background.colorMap.loadFromFile(getAssetPath() + "textures/stonefloor02_color_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.background.normalMap.loadFromFile(getAssetPath() + "textures/stonefloor02_normal_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 8), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 9) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - // Deferred shading layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Position texture target / Scene colormap - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 2 : Normals texture target - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - // Binding 3 : Albedo texture target - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), - // Binding 4 : Fragment shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 4), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - std::vector writeDescriptorSets; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - // Image descriptors for the offscreen color attachments - VkDescriptorImageInfo texDescriptorPosition = - vks::initializers::descriptorImageInfo( - offscreenframeBuffers->sampler, - offscreenframeBuffers->attachments[0].view, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - VkDescriptorImageInfo texDescriptorNormal = - vks::initializers::descriptorImageInfo( - offscreenframeBuffers->sampler, - offscreenframeBuffers->attachments[1].view, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - VkDescriptorImageInfo texDescriptorAlbedo = - vks::initializers::descriptorImageInfo( - offscreenframeBuffers->sampler, - offscreenframeBuffers->attachments[2].view, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Deferred composition - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.composition)); - writeDescriptorSets = { - // Binding 1: World space position texture - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &texDescriptorPosition), - // Binding 2: World space normals texture - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &texDescriptorNormal), - // Binding 3: Albedo texture - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &texDescriptorAlbedo), - // Binding 4: Fragment shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4, &uniformBuffers.composition.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Offscreen (scene) - - // Model - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.model)); - writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.model, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.offscreen.descriptor), - // Binding 1: Color map - vks::initializers::writeDescriptorSet(descriptorSets.model, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.model.colorMap.descriptor), - // Binding 2: Normal map - vks::initializers::writeDescriptorSet(descriptorSets.model, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.model.normalMap.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Background - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.background)); - writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.background, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.offscreen.descriptor), - // Binding 1: Color map - vks::initializers::writeDescriptorSet(descriptorSets.background, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.background.colorMap.descriptor), - // Binding 2: Normal map - vks::initializers::writeDescriptorSet(descriptorSets.background, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.background.normalMap.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Fullscreen composition pass - - // Empty vertex input state, vertices are generated by the vertex shader - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCI.pVertexInputState = &emptyInputState; - - // Use specialization constants to pass number of samples to the shader (used for MSAA resolve) - VkSpecializationMapEntry specializationEntry{}; - specializationEntry.constantID = 0; - specializationEntry.offset = 0; - specializationEntry.size = sizeof(uint32_t); - - uint32_t specializationData = sampleCount; - - VkSpecializationInfo specializationInfo; - specializationInfo.mapEntryCount = 1; - specializationInfo.pMapEntries = &specializationEntry; - specializationInfo.dataSize = sizeof(specializationData); - specializationInfo.pData = &specializationData; - - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - - // With MSAA - shaderStages[0] = loadShader(getShadersPath() + "deferredmultisampling/deferred.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "deferredmultisampling/deferred.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - shaderStages[1].pSpecializationInfo = &specializationInfo; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.deferred)); - - // No MSAA (1 sample) - specializationData = 1; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.deferredNoMSAA)); - - // Vertex input state from glTF model for pipeline rendering models - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Tangent }); - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - - // Offscreen scene rendering pipeline - // Separate render pass - pipelineCI.renderPass = offscreenframeBuffers->renderPass; - - shaderStages[0] = loadShader(getShadersPath() + "deferredmultisampling/mrt.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "deferredmultisampling/mrt.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - //rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; - //rasterizationState.lineWidth = 2.0f; - multisampleState.rasterizationSamples = sampleCount; - multisampleState.alphaToCoverageEnable = VK_TRUE; - - // Blend attachment states required for all color attachments - // This is important, as color write mask will otherwise be 0x0 and you - // won't see anything rendered to the attachment - std::array blendAttachmentStates = { - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE) - }; - - colorBlendState.attachmentCount = static_cast(blendAttachmentStates.size()); - colorBlendState.pAttachments = blendAttachmentStates.data(); - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.offscreen)); - - multisampleState.sampleShadingEnable = VK_TRUE; - multisampleState.minSampleShading = 0.25f; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.offscreenSampleShading)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Offscreen vertex shader - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.offscreen, sizeof(UniformDataOffscreen))); - // Deferred fragment shader - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.composition, sizeof(UniformDataComposition)));; - // Map persistent - VK_CHECK_RESULT(uniformBuffers.offscreen.map()); - VK_CHECK_RESULT(uniformBuffers.composition.map()); - - // Setup instanced model positions - uniformDataOffscreen.instancePos[0] = glm::vec4(0.0f); - uniformDataOffscreen.instancePos[1] = glm::vec4(-4.0f, 0.0, -4.0f, 0.0f); - uniformDataOffscreen.instancePos[2] = glm::vec4(4.0f, 0.0, -4.0f, 0.0f); - - // Update - updateUniformBufferDeferred(); - } - - void updateUniformBufferOffscreen() - { - uniformDataOffscreen.projection = camera.matrices.perspective; - uniformDataOffscreen.view = camera.matrices.view; - uniformDataOffscreen.model = glm::mat4(1.0f); - memcpy(uniformBuffers.offscreen.mapped, &uniformDataOffscreen, sizeof(UniformDataOffscreen)); - } - - // Update deferred composition fragment shader light position and parameters uniform block - void updateUniformBufferDeferred() - { - // White - uniformDataComposition.lights[0].position = glm::vec4(0.0f, 0.0f, 5.0f, 0.0f); - uniformDataComposition.lights[0].color = glm::vec3(1.5f); - uniformDataComposition.lights[0].radius = 15.0f * 0.25f; - // Red - uniformDataComposition.lights[1].position = glm::vec4(-2.30f, 0.0f, 1.05f, 0.0f); - uniformDataComposition.lights[1].color = glm::vec3(1.0f, 0.0f, 0.0f); - uniformDataComposition.lights[1].radius = 15.0f; - // Blue - uniformDataComposition.lights[2].position = glm::vec4(4.0f, -1.0f, 2.0f, 0.0f); - uniformDataComposition.lights[2].color = glm::vec3(0.0f, 0.0f, 2.5f); - uniformDataComposition.lights[2].radius = 5.0f; - // Yellow - uniformDataComposition.lights[3].position = glm::vec4(0.0f, -0.9f, 0.5f, 0.0f); - uniformDataComposition.lights[3].color = glm::vec3(1.0f, 1.0f, 0.0f); - uniformDataComposition.lights[3].radius = 2.0f; - // Green - uniformDataComposition.lights[4].position = glm::vec4(5.0f, -0.5f, -3.53f, 0.0f); - uniformDataComposition.lights[4].color = glm::vec3(0.0f, 1.0f, 0.2f); - uniformDataComposition.lights[4].radius = 5.0f; - // Yellow - uniformDataComposition.lights[5].position = glm::vec4(7.07f, -1.0f, 7.07f, 0.0f); - uniformDataComposition.lights[5].color = glm::vec3(1.0f, 0.7f, 0.3f); - uniformDataComposition.lights[5].radius = 25.0f; - - // Current view position - uniformDataComposition.viewPos = glm::vec4(camera.position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f); - uniformDataComposition.debugDisplayTarget = debugDisplayTarget; - - memcpy(uniformBuffers.composition.mapped, &uniformDataComposition, sizeof(UniformDataComposition)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - sampleCount = getMaxUsableSampleCount(); - loadAssets(); - deferredSetup(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - buildDeferredCommandBuffer(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - - // Offscreen rendering - - // Wait for swap chain presentation to finish - submitInfo.pWaitSemaphores = &semaphores.presentComplete; - // Signal ready with offscreen semaphore - submitInfo.pSignalSemaphores = &offscreenSemaphore; - - // Submit work - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &offScreenCmdBuffer; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - // Scene rendering - - // Wait for offscreen semaphore - submitInfo.pWaitSemaphores = &offscreenSemaphore; - // Signal ready with render complete semaphore - submitInfo.pSignalSemaphores = &semaphores.renderComplete; - - // Submit work - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBufferOffscreen(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->comboBox("Display", &debugDisplayTarget, { "Final composition", "Position", "Normals", "Albedo", "Specular" })) { - updateUniformBufferDeferred(); - } - if (overlay->checkBox("MSAA", &useMSAA)) { - buildCommandBuffers(); - } - if (vulkanDevice->features.sampleRateShading) { - if (overlay->checkBox("Sample rate shading", &useSampleShading)) { - buildDeferredCommandBuffer(); - } - } - } - } - - // Returns the maximum sample count usable by the platform - VkSampleCountFlagBits getMaxUsableSampleCount() - { - VkSampleCountFlags counts = std::min(deviceProperties.limits.framebufferColorSampleCounts, deviceProperties.limits.framebufferDepthSampleCounts); - // Note: Vulkan offers up to 64 bits, but we don't want to go higher than 8xMSAA in this sample) - if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; } - if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; } - if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; } - return VK_SAMPLE_COUNT_1_BIT; - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/deferredshadows/deferredshadows.cpp b/examples/deferredshadows/deferredshadows.cpp deleted file mode 100644 index 3cc9fc6b..00000000 --- a/examples/deferredshadows/deferredshadows.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/* -* Vulkan Example - Deferred shading with shadows from multiple light sources using geometry shader instancing -* -* This sample adds dynamic shadows (using shadow maps) to a deferred rendering setup -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanFrameBuffer.hpp" -#include "VulkanglTFModel.h" - -// Must match the LIGHT_COUNT define in the shadow and deferred shaders -#define LIGHT_COUNT 3 - -class VulkanExample : public VulkanExampleBase -{ -public: - int32_t debugDisplayTarget = 0; - bool enableShadows = true; - - // Keep depth range as small as possible - // for better shadow map precision - float zNear = 0.1f; - float zFar = 64.0f; - float lightFOV = 100.0f; - - // Depth bias (and slope) are used to avoid shadowing artifacts - float depthBiasConstant = 1.25f; - float depthBiasSlope = 1.75f; - - struct { - struct { - vks::Texture2D colorMap; - vks::Texture2D normalMap; - } model; - struct { - vks::Texture2D colorMap; - vks::Texture2D normalMap; - } background; - } textures; - - struct { - vkglTF::Model model; - vkglTF::Model background; - } models; - - struct UniformDataOffscreen { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - glm::vec4 instancePos[3]; - int layer{ 0 }; - } uniformDataOffscreen; - - // This UBO stores the shadow matrices for all of the light sources - // The matrices are indexed using geometry shader instancing - // The instancePos is used to place the models using instanced draws - struct UniformDataShadows { - glm::mat4 mvp[LIGHT_COUNT]; - glm::vec4 instancePos[3]; - } uniformDataShadows; - - struct Light { - glm::vec4 position; - glm::vec4 target; - glm::vec4 color; - glm::mat4 viewMatrix; - }; - - struct UniformDataComposition { - glm::vec4 viewPos; - Light lights[LIGHT_COUNT]; - uint32_t useShadows = 1; - int32_t debugDisplayTarget = 0; - } uniformDataComposition; - - struct { - vks::Buffer offscreen; - vks::Buffer composition; - vks::Buffer shadowGeometryShader; - } uniformBuffers; - - struct { - VkPipeline deferred{ VK_NULL_HANDLE }; - VkPipeline offscreen{ VK_NULL_HANDLE }; - VkPipeline shadowpass{ VK_NULL_HANDLE }; - } pipelines; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - - struct { - VkDescriptorSet model{ VK_NULL_HANDLE }; - VkDescriptorSet background{ VK_NULL_HANDLE }; - VkDescriptorSet shadow{ VK_NULL_HANDLE }; - VkDescriptorSet composition{ VK_NULL_HANDLE }; - } descriptorSets; - - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - struct { - // Framebuffer resources for the deferred pass - vks::Framebuffer *deferred; - // Framebuffer resources for the shadow pass - vks::Framebuffer *shadow; - } frameBuffers{}; - - VkCommandBuffer offScreenCmdBuffer{ VK_NULL_HANDLE }; - - // Semaphore used to synchronize between offscreen and final scene rendering - VkSemaphore offscreenSemaphore{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Deferred shading with shadows"; - camera.type = Camera::CameraType::firstperson; -#if defined(__ANDROID__) - camera.movementSpeed = 2.5f; -#else - camera.movementSpeed = 5.0f; - camera.rotationSpeed = 0.25f; -#endif - camera.position = { 2.15f, 0.3f, -8.75f }; - camera.setRotation(glm::vec3(-0.75f, 12.5f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, zNear, zFar); - timerSpeed *= 0.25f; - } - - ~VulkanExample() - { - // Frame buffers - if (frameBuffers.deferred) - { - delete frameBuffers.deferred; - } - if (frameBuffers.shadow) - { - delete frameBuffers.shadow; - } - - vkDestroyPipeline(device, pipelines.deferred, nullptr); - vkDestroyPipeline(device, pipelines.offscreen, nullptr); - vkDestroyPipeline(device, pipelines.shadowpass, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - // Uniform buffers - uniformBuffers.composition.destroy(); - uniformBuffers.offscreen.destroy(); - uniformBuffers.shadowGeometryShader.destroy(); - - // Textures - textures.model.colorMap.destroy(); - textures.model.normalMap.destroy(); - textures.background.colorMap.destroy(); - textures.background.normalMap.destroy(); - - vkDestroySemaphore(device, offscreenSemaphore, nullptr); - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Geometry shader support is required for writing to multiple shadow map layers in one single pass - if (deviceFeatures.geometryShader) { - enabledFeatures.geometryShader = VK_TRUE; - } - else { - vks::tools::exitFatal("Selected GPU does not support geometry shaders!", VK_ERROR_FEATURE_NOT_PRESENT); - } - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - // Enable texture compression - if (deviceFeatures.textureCompressionBC) { - enabledFeatures.textureCompressionBC = VK_TRUE; - } - else if (deviceFeatures.textureCompressionASTC_LDR) { - enabledFeatures.textureCompressionASTC_LDR = VK_TRUE; - } - else if (deviceFeatures.textureCompressionETC2) { - enabledFeatures.textureCompressionETC2 = VK_TRUE; - } - } - - // Prepare a layered shadow map with each layer containing depth from a light's point of view - // The shadow mapping pass uses geometry shader instancing to output the scene from the different - // light sources' point of view to the layers of the depth attachment in one single pass - void shadowSetup() - { - frameBuffers.shadow = new vks::Framebuffer(vulkanDevice); - - // Shadowmap properties -#if defined(__ANDROID__) - // Use smaller shadow maps on mobile due to performance reasons - frameBuffers.shadow->width = 1024; - frameBuffers.shadow->height = 1024; -#else - frameBuffers.shadow->width = 2048; - frameBuffers.shadow->height = 2048; -#endif - - // Find a suitable depth format - VkFormat shadowMapFormat; - VkBool32 validShadowMapFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &shadowMapFormat); - assert(validShadowMapFormat); - - // Create a layered depth attachment for rendering the depth maps from the lights' point of view - // Each layer corresponds to one of the lights - // The actual output to the separate layers is done in the geometry shader using shader instancing - // We will pass the matrices of the lights to the GS that selects the layer by the current invocation - vks::AttachmentCreateInfo attachmentInfo = {}; - attachmentInfo.format = shadowMapFormat; - attachmentInfo.width = frameBuffers.shadow->width; - attachmentInfo.height = frameBuffers.shadow->height; - attachmentInfo.layerCount = LIGHT_COUNT; - attachmentInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - frameBuffers.shadow->addAttachment(attachmentInfo); - - // Create sampler to sample from to depth attachment - // Used to sample in the fragment shader for shadowed rendering - VK_CHECK_RESULT(frameBuffers.shadow->createSampler(VK_FILTER_LINEAR, VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)); - - // Create default renderpass for the framebuffer - VK_CHECK_RESULT(frameBuffers.shadow->createRenderPass()); - } - - // Prepare the framebuffer for offscreen rendering with multiple attachments used as render targets inside the fragment shaders - void deferredSetup() - { - frameBuffers.deferred = new vks::Framebuffer(vulkanDevice); - -#if defined(__ANDROID__) - // Use max. screen dimension as deferred framebuffer size - frameBuffers.deferred->width = std::max(width, height); - frameBuffers.deferred->height = std::max(width, height); -#else - frameBuffers.deferred->width = 2048; - frameBuffers.deferred->height = 2048; -#endif - - // Four attachments (3 color, 1 depth) - vks::AttachmentCreateInfo attachmentInfo = {}; - attachmentInfo.width = frameBuffers.deferred->width; - attachmentInfo.height = frameBuffers.deferred->height; - attachmentInfo.layerCount = 1; - attachmentInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - - // Color attachments - // Attachment 0: (World space) Positions - attachmentInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT; - frameBuffers.deferred->addAttachment(attachmentInfo); - - // Attachment 1: (World space) Normals - attachmentInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT; - frameBuffers.deferred->addAttachment(attachmentInfo); - - // Attachment 2: Albedo (color) - attachmentInfo.format = VK_FORMAT_R8G8B8A8_UNORM; - frameBuffers.deferred->addAttachment(attachmentInfo); - - // Depth attachment - // Find a suitable depth format - VkFormat attDepthFormat; - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attDepthFormat); - assert(validDepthFormat); - - attachmentInfo.format = attDepthFormat; - attachmentInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - frameBuffers.deferred->addAttachment(attachmentInfo); - - // Create sampler to sample from the color attachments - VK_CHECK_RESULT(frameBuffers.deferred->createSampler(VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)); - - // Create default renderpass for the framebuffer - VK_CHECK_RESULT(frameBuffers.deferred->createRenderPass()); - } - - // Put render commands for the scene into the given command buffer - void renderScene(VkCommandBuffer cmdBuffer, bool shadow) - { - // Background - vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, shadow ? &descriptorSets.shadow : &descriptorSets.background, 0, NULL); - models.background.draw(cmdBuffer); - - // Objects - vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, shadow ? &descriptorSets.shadow : &descriptorSets.model, 0, NULL); - models.model.bindBuffers(cmdBuffer); - vkCmdDrawIndexed(cmdBuffer, models.model.indices.count, 3, 0, 0, 0); - } - - // Build a secondary command buffer for rendering the scene values to the offscreen frame buffer attachments - void buildDeferredCommandBuffer() - { - if (offScreenCmdBuffer == VK_NULL_HANDLE) { - offScreenCmdBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false); - } - - // Create a semaphore used to synchronize offscreen rendering and usage - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &offscreenSemaphore)); - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - std::array clearValues = {}; - VkViewport viewport; - VkRect2D scissor; - - // First pass: Shadow map generation - // ------------------------------------------------------------------------------------------------------- - - clearValues[0].depthStencil = { 1.0f, 0 }; - - renderPassBeginInfo.renderPass = frameBuffers.shadow->renderPass; - renderPassBeginInfo.framebuffer = frameBuffers.shadow->framebuffer; - renderPassBeginInfo.renderArea.extent.width = frameBuffers.shadow->width; - renderPassBeginInfo.renderArea.extent.height = frameBuffers.shadow->height; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = clearValues.data(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(offScreenCmdBuffer, &cmdBufInfo)); - - viewport = vks::initializers::viewport((float)frameBuffers.shadow->width, (float)frameBuffers.shadow->height, 0.0f, 1.0f); - vkCmdSetViewport(offScreenCmdBuffer, 0, 1, &viewport); - - scissor = vks::initializers::rect2D(frameBuffers.shadow->width, frameBuffers.shadow->height, 0, 0); - vkCmdSetScissor(offScreenCmdBuffer, 0, 1, &scissor); - - // Set depth bias (aka "Polygon offset") - vkCmdSetDepthBias( - offScreenCmdBuffer, - depthBiasConstant, - 0.0f, - depthBiasSlope); - - vkCmdBeginRenderPass(offScreenCmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.shadowpass); - renderScene(offScreenCmdBuffer, true); - vkCmdEndRenderPass(offScreenCmdBuffer); - - // Second pass: Deferred calculations - // ------------------------------------------------------------------------------------------------------- - - // Clear values for all attachments written in the fragment shader - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[2].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[3].depthStencil = { 1.0f, 0 }; - - renderPassBeginInfo.renderPass = frameBuffers.deferred->renderPass; - renderPassBeginInfo.framebuffer = frameBuffers.deferred->framebuffer; - renderPassBeginInfo.renderArea.extent.width = frameBuffers.deferred->width; - renderPassBeginInfo.renderArea.extent.height = frameBuffers.deferred->height; - renderPassBeginInfo.clearValueCount = static_cast(clearValues.size()); - renderPassBeginInfo.pClearValues = clearValues.data(); - - vkCmdBeginRenderPass(offScreenCmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - viewport = vks::initializers::viewport((float)frameBuffers.deferred->width, (float)frameBuffers.deferred->height, 0.0f, 1.0f); - vkCmdSetViewport(offScreenCmdBuffer, 0, 1, &viewport); - - scissor = vks::initializers::rect2D(frameBuffers.deferred->width, frameBuffers.deferred->height, 0, 0); - vkCmdSetScissor(offScreenCmdBuffer, 0, 1, &scissor); - - vkCmdBindPipeline(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.offscreen); - renderScene(offScreenCmdBuffer, false); - vkCmdEndRenderPass(offScreenCmdBuffer); - - VK_CHECK_RESULT(vkEndCommandBuffer(offScreenCmdBuffer)); - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.model.loadFromFile(getAssetPath() + "models/armor/armor.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.background.loadFromFile(getAssetPath() + "models/deferred_box.gltf", vulkanDevice, queue, glTFLoadingFlags); - textures.model.colorMap.loadFromFile(getAssetPath() + "models/armor/colormap_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.model.normalMap.loadFromFile(getAssetPath() + "models/armor/normalmap_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.background.colorMap.loadFromFile(getAssetPath() + "textures/stonefloor02_color_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.background.normalMap.loadFromFile(getAssetPath() + "textures/stonefloor02_normal_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = VulkanExampleBase::frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.composition, 0, nullptr); - - // Final composition as full screen quad - // Note: Also used for debug display if debugDisplayTarget > 0 - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.deferred); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 12), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 16) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo =vks::initializers::descriptorPoolCreateInfo(poolSizes, 4); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, 0), - // Binding 1: Position texture - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 2: Normals texture - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - // Binding 3: Albedo texture - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), - // Binding 4: Fragment shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 4), - // Binding 5: Shadow map - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 5), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - std::vector writeDescriptorSets; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - // Image descriptors for the offscreen color attachments - VkDescriptorImageInfo texDescriptorPosition = - vks::initializers::descriptorImageInfo( - frameBuffers.deferred->sampler, - frameBuffers.deferred->attachments[0].view, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - VkDescriptorImageInfo texDescriptorNormal = - vks::initializers::descriptorImageInfo( - frameBuffers.deferred->sampler, - frameBuffers.deferred->attachments[1].view, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - VkDescriptorImageInfo texDescriptorAlbedo = - vks::initializers::descriptorImageInfo( - frameBuffers.deferred->sampler, - frameBuffers.deferred->attachments[2].view, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - VkDescriptorImageInfo texDescriptorShadowMap = - vks::initializers::descriptorImageInfo( - frameBuffers.shadow->sampler, - frameBuffers.shadow->attachments[0].view, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); - - // Deferred composition - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.composition)); - writeDescriptorSets = { - // Binding 1: World space position texture - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &texDescriptorPosition), - // Binding 2: World space normals texture - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &texDescriptorNormal), - // Binding 3: Albedo texture - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &texDescriptorAlbedo), - // Binding 4: Fragment shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4, &uniformBuffers.composition.descriptor), - // Binding 5: Shadow map - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 5, &texDescriptorShadowMap), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Offscreen (scene) - - // Model - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.model)); - writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.model, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.offscreen.descriptor), - // Binding 1: Color map - vks::initializers::writeDescriptorSet(descriptorSets.model, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.model.colorMap.descriptor), - // Binding 2: Normal map - vks::initializers::writeDescriptorSet(descriptorSets.model, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.model.normalMap.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Background - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.background)); - writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.background, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.offscreen.descriptor), - // Binding 1: Color map - vks::initializers::writeDescriptorSet(descriptorSets.background, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.background.colorMap.descriptor), - // Binding 2: Normal map - vks::initializers::writeDescriptorSet(descriptorSets.background, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.background.normalMap.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Shadow mapping - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.shadow)); - writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.shadow, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.shadowGeometryShader.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Final fullscreen composition pass pipeline - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - shaderStages[0] = loadShader(getShadersPath() + "deferredshadows/deferred.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "deferredshadows/deferred.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Empty vertex input state, vertices are generated by the vertex shader - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCI.pVertexInputState = &emptyInputState; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.deferred)); - - // Vertex input state from glTF model for pipeline rendering models - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Tangent }); - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - - // Offscreen pipeline - // Separate render pass - pipelineCI.renderPass = frameBuffers.deferred->renderPass; - - // Blend attachment states required for all color attachments - // This is important, as color write mask will otherwise be 0x0 and you - // won't see anything rendered to the attachment - std::array blendAttachmentStates = - { - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE) - }; - colorBlendState.attachmentCount = static_cast(blendAttachmentStates.size()); - colorBlendState.pAttachments = blendAttachmentStates.data(); - - shaderStages[0] = loadShader(getShadersPath() + "deferredshadows/mrt.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "deferredshadows/mrt.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.offscreen)); - - // Shadow mapping pipeline - // The shadow mapping pipeline uses geometry shader instancing (invocations layout modifier) to output - // shadow maps for multiple lights sources into the different shadow map layers in one single render pass - std::array shadowStages; - shadowStages[0] = loadShader(getShadersPath() + "deferredshadows/shadow.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shadowStages[1] = loadShader(getShadersPath() + "deferredshadows/shadow.geom.spv", VK_SHADER_STAGE_GEOMETRY_BIT); - - pipelineCI.pStages = shadowStages.data(); - pipelineCI.stageCount = static_cast(shadowStages.size()); - - // Shadow pass doesn't use any color attachments - colorBlendState.attachmentCount = 0; - colorBlendState.pAttachments = nullptr; - // Cull front faces - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - depthStencilState.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; - // Enable depth bias - rasterizationState.depthBiasEnable = VK_TRUE; - // Add depth bias to dynamic state, so we can change it at runtime - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_DEPTH_BIAS); - dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - // Reset blend attachment state - pipelineCI.renderPass = frameBuffers.shadow->renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.shadowpass)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Offscreen vertex shader - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.offscreen, sizeof(UniformDataOffscreen))); - - // Deferred fragment shader - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.composition, sizeof(UniformDataComposition))); - - // Shadow map vertex shader (matrices from shadow's pov) - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.shadowGeometryShader, sizeof(UniformDataShadows))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffers.offscreen.map()); - VK_CHECK_RESULT(uniformBuffers.composition.map()); - VK_CHECK_RESULT(uniformBuffers.shadowGeometryShader.map()); - - // Setup instanced model positions - uniformDataOffscreen.instancePos[0] = glm::vec4(0.0f); - uniformDataOffscreen.instancePos[1] = glm::vec4(-7.0f, 0.0, -4.0f, 0.0f); - uniformDataOffscreen.instancePos[2] = glm::vec4(4.0f, 0.0, -6.0f, 0.0f); - } - - void updateUniformBufferOffscreen() - { - uniformDataOffscreen.projection = camera.matrices.perspective; - uniformDataOffscreen.view = camera.matrices.view; - uniformDataOffscreen.model = glm::mat4(1.0f); - memcpy(uniformBuffers.offscreen.mapped, &uniformDataOffscreen, sizeof(uniformDataOffscreen)); - } - - Light initLight(glm::vec3 pos, glm::vec3 target, glm::vec3 color) - { - Light light; - light.position = glm::vec4(pos, 1.0f); - light.target = glm::vec4(target, 0.0f); - light.color = glm::vec4(color, 0.0f); - return light; - } - - void initLights() - { - uniformDataComposition.lights[0] = initLight(glm::vec3(-14.0f, -0.5f, 15.0f), glm::vec3(-2.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.5f, 0.5f)); - uniformDataComposition.lights[1] = initLight(glm::vec3(14.0f, -4.0f, 12.0f), glm::vec3(2.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); - uniformDataComposition.lights[2] = initLight(glm::vec3(0.0f, -10.0f, 4.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f)); - } - - // Update deferred composition fragment shader light position and parameters uniform block - void updateUniformBufferDeferred() - { - // Animate - uniformDataComposition.lights[0].position.x = -14.0f + std::abs(sin(glm::radians(timer * 360.0f)) * 20.0f); - uniformDataComposition.lights[0].position.z = 15.0f + cos(glm::radians(timer *360.0f)) * 1.0f; - - uniformDataComposition.lights[1].position.x = 14.0f - std::abs(sin(glm::radians(timer * 360.0f)) * 2.5f); - uniformDataComposition.lights[1].position.z = 13.0f + cos(glm::radians(timer *360.0f)) * 4.0f; - - uniformDataComposition.lights[2].position.x = 0.0f + sin(glm::radians(timer *360.0f)) * 4.0f; - uniformDataComposition.lights[2].position.z = 4.0f + cos(glm::radians(timer *360.0f)) * 2.0f; - - for (uint32_t i = 0; i < LIGHT_COUNT; i++) { - // mvp from light's pov (for shadows) - glm::mat4 shadowProj = glm::perspective(glm::radians(lightFOV), 1.0f, zNear, zFar); - glm::mat4 shadowView = glm::lookAt(glm::vec3(uniformDataComposition.lights[i].position), glm::vec3(uniformDataComposition.lights[i].target), glm::vec3(0.0f, 1.0f, 0.0f)); - glm::mat4 shadowModel = glm::mat4(1.0f); - - uniformDataShadows.mvp[i] = shadowProj * shadowView * shadowModel; - uniformDataComposition.lights[i].viewMatrix = uniformDataShadows.mvp[i]; - } - - memcpy(uniformDataShadows.instancePos, uniformDataOffscreen.instancePos, sizeof(UniformDataOffscreen::instancePos)); - memcpy(uniformBuffers.shadowGeometryShader.mapped, &uniformDataShadows, sizeof(UniformDataShadows)); - - uniformDataComposition.viewPos = glm::vec4(camera.position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f);; - uniformDataComposition.debugDisplayTarget = debugDisplayTarget; - - memcpy(uniformBuffers.composition.mapped, &uniformDataComposition, sizeof(uniformDataComposition)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - deferredSetup(); - shadowSetup(); - initLights(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - buildDeferredCommandBuffer(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - - // Offscreen rendering - - // Wait for swap chain presentation to finish - submitInfo.pWaitSemaphores = &semaphores.presentComplete; - // Signal ready with offscreen semaphore - submitInfo.pSignalSemaphores = &offscreenSemaphore; - - // Submit work - - // Shadow map pass - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &offScreenCmdBuffer; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - // Scene rendering - - // Wait for offscreen semaphore - submitInfo.pWaitSemaphores = &offscreenSemaphore; - // Signal ready with render complete semaphore - submitInfo.pSignalSemaphores = &semaphores.renderComplete; - - // Submit work - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBufferDeferred(); - updateUniformBufferOffscreen(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->comboBox("Display", &debugDisplayTarget, { "Final composition", "Shadows", "Position", "Normals", "Albedo", "Specular" }); - bool shadows = (uniformDataComposition.useShadows == 1); - if (overlay->checkBox("Shadows", &shadows)) { - uniformDataComposition.useShadows = shadows; - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/descriptorbuffer/descriptorbuffer.cpp b/examples/descriptorbuffer/descriptorbuffer.cpp deleted file mode 100644 index 951e8027..00000000 --- a/examples/descriptorbuffer/descriptorbuffer.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/* - * Vulkan Example - Using descriptor buffers via VK_EXT_descriptor_buffer - * - * Copyright (C) 2022-2024 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - - -class VulkanExample : public VulkanExampleBase -{ -public: - bool animate = true; - - struct Cube { - glm::mat4 matrix; - vks::Texture2D texture; - vks::Buffer uniformBuffer; - glm::vec3 rotation; - }; - std::array cubes; - - vks::Buffer uniformBufferCamera; - - vkglTF::Model model; - - VkPipeline pipeline; - VkPipelineLayout pipelineLayout; - - PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; - - VkPhysicalDeviceDescriptorBufferFeaturesEXT enabledDeviceDescriptorBufferFeaturesEXT{}; - VkPhysicalDeviceBufferDeviceAddressFeatures enabledBufferDeviceAddresFeatures{}; - VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptorBufferProperties{}; - - PFN_vkGetDescriptorSetLayoutSizeEXT vkGetDescriptorSetLayoutSizeEXT; - PFN_vkGetDescriptorSetLayoutBindingOffsetEXT vkGetDescriptorSetLayoutBindingOffsetEXT; - PFN_vkCmdBindDescriptorBuffersEXT vkCmdBindDescriptorBuffersEXT; - PFN_vkCmdSetDescriptorBufferOffsetsEXT vkCmdSetDescriptorBufferOffsetsEXT; - PFN_vkGetDescriptorEXT vkGetDescriptorEXT; - PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT vkCmdBindDescriptorBufferEmbeddedSamplersEXT; - - // Stores all values that are required to setup a descriptor buffer for a resource buffer - struct DescriptorInfo { - VkDeviceSize layoutOffset; - VkDeviceSize layoutSize; - VkDescriptorSetLayout setLayout; - VkDeviceOrHostAddressConstKHR bufferDeviceAddress; - vks::Buffer buffer; - }; - DescriptorInfo uniformDescriptor{}; - DescriptorInfo combinedImageDescriptor{}; - - uint64_t getBufferDeviceAddress(VkBuffer buffer) - { - VkBufferDeviceAddressInfoKHR bufferDeviceAI{}; - bufferDeviceAI.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; - bufferDeviceAI.buffer = buffer; - return vkGetBufferDeviceAddressKHR(vulkanDevice->logicalDevice, &bufferDeviceAI); - } - - VulkanExample() : VulkanExampleBase() - { - title = "Descriptor buffers (VK_EXT_descriptor_buffer)"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -5.0f)); - - apiVersion = VK_API_VERSION_1_1; - - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - - enabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); - - enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); - - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledDeviceDescriptorBufferFeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT; - enabledDeviceDescriptorBufferFeaturesEXT.descriptorBuffer = VK_TRUE; - enabledDeviceDescriptorBufferFeaturesEXT.pNext = &enabledBufferDeviceAddresFeatures; - - deviceCreatepNextChain = &enabledDeviceDescriptorBufferFeaturesEXT; - } - - ~VulkanExample() - { - vkDestroyDescriptorSetLayout(device, uniformDescriptor.setLayout, nullptr); - vkDestroyDescriptorSetLayout(device, combinedImageDescriptor.setLayout, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - for (auto& cube : cubes) { - cube.uniformBuffer.destroy(); - cube.texture.destroy(); - } - uniformBufferCamera.destroy(); - uniformDescriptor.buffer.destroy(); - combinedImageDescriptor.buffer.destroy(); - } - - virtual void getEnabledFeatures() - { - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - }; - } - - void setupDescriptors() - { - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI{}; - descriptorLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptorLayoutCI.bindingCount = 1; - descriptorLayoutCI.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; - - VkDescriptorSetLayoutBinding setLayoutBinding = {}; - - setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - setLayoutBinding.binding = 0; - setLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - setLayoutBinding.descriptorCount = 1; - - descriptorLayoutCI.pBindings = &setLayoutBinding; - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &uniformDescriptor.setLayout)); - - setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - setLayoutBinding.binding = 0; - setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - setLayoutBinding.descriptorCount = 1; - - descriptorLayoutCI.pBindings = &setLayoutBinding; - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &combinedImageDescriptor.setLayout)); - } - - void preparePipelines() - { - // Set 0 = Camera UBO - // Set 1 = Model UBO - // Set 2 = Model image - const std::array setLayouts = { uniformDescriptor.setLayout, uniformDescriptor.setLayout, combinedImageDescriptor.setLayout }; - - VkPipelineLayoutCreateInfo pipelineLayoutCI{}; - pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - // The pipeline layout is based on the descriptor set layout we created above - pipelineLayoutCI.setLayoutCount = static_cast(setLayouts.size()); - pipelineLayoutCI.pSetLayouts = setLayouts.data(); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); - std::array shaderStages = { - loadShader(getShadersPath() + "descriptorbuffer/cube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "descriptorbuffer/cube.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color }); - pipelineCI.flags = VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareDescriptorBuffer() - { - // We need to get sizes and offsets for the descriptor layouts - - // This is done using a new extension structures and features - PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR")); - assert(vkGetPhysicalDeviceProperties2KHR); - VkPhysicalDeviceProperties2KHR deviceProps2{}; - descriptorBufferProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT; - deviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; - deviceProps2.pNext = &descriptorBufferProperties; - vkGetPhysicalDeviceProperties2KHR(physicalDevice, &deviceProps2); - - // Some devices have very low limits for the no. of max descriptor buffer bindings, so we need to check - if (descriptorBufferProperties.maxResourceDescriptorBufferBindings < 2) { - vks::tools::exitFatal("This sample requires at least 2 descriptor bindings to run, the selected device only supports " + std::to_string(descriptorBufferProperties.maxResourceDescriptorBufferBindings), - 1); - } - - vkGetDescriptorSetLayoutSizeEXT(device, uniformDescriptor.setLayout, &uniformDescriptor.layoutSize); - vkGetDescriptorSetLayoutSizeEXT(device, combinedImageDescriptor.setLayout, &combinedImageDescriptor.layoutSize); - - vkGetDescriptorSetLayoutBindingOffsetEXT(device, uniformDescriptor.setLayout, 0, &uniformDescriptor.layoutOffset); - vkGetDescriptorSetLayoutBindingOffsetEXT(device, combinedImageDescriptor.setLayout, 0, &combinedImageDescriptor.layoutOffset); - - // In order to copy resource descriptors to the correct place, we need to calculate aligned sizes - uniformDescriptor.layoutSize = vks::tools::alignedVkSize(uniformDescriptor.layoutSize, descriptorBufferProperties.descriptorBufferOffsetAlignment); - combinedImageDescriptor.layoutSize = vks::tools::alignedVkSize(combinedImageDescriptor.layoutSize, descriptorBufferProperties.descriptorBufferOffsetAlignment); - - // This buffer will contain resource descriptors for all the uniform buffers (one per cube and one with global matrices) - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformDescriptor.buffer, - (static_cast(cubes.size()) + 1) * uniformDescriptor.layoutSize)); - uniformDescriptor.buffer.map(); - - // This buffer contains resource descriptors for the combined images (one per cube) - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT | VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, // Flags 1 & 2 are required for combined images - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &combinedImageDescriptor.buffer, - static_cast(cubes.size()) * combinedImageDescriptor.layoutSize)); - combinedImageDescriptor.buffer.map(); - - uniformDescriptor.bufferDeviceAddress.deviceAddress = getBufferDeviceAddress(uniformDescriptor.buffer.buffer); - combinedImageDescriptor.bufferDeviceAddress.deviceAddress = getBufferDeviceAddress(combinedImageDescriptor.buffer.buffer); - - VkDescriptorGetInfoEXT descriptorInfo{}; - descriptorInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT; - - // Put image descriptors into the corresponding resource buffer - char* imageDescriptorBufPtr = (char*)combinedImageDescriptor.buffer.mapped; - descriptorInfo.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - for (uint32_t i = 0; i < static_cast(cubes.size()); i++) { - descriptorInfo.data.pCombinedImageSampler = &cubes[i].texture.descriptor; - vkGetDescriptorEXT(device, &descriptorInfo, descriptorBufferProperties.combinedImageSamplerDescriptorSize, imageDescriptorBufPtr + i * combinedImageDescriptor.layoutSize + combinedImageDescriptor.layoutOffset); - } - - // For uniform buffers we only need buffer device addresses - // Global uniform buffer - char* uniformDescriptorBufPtr = (char*)uniformDescriptor.buffer.mapped; - - VkDescriptorAddressInfoEXT descriptorAddressInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT }; - descriptorAddressInfo.address = getBufferDeviceAddress(uniformBufferCamera.buffer); - descriptorAddressInfo.range = uniformBufferCamera.size; - descriptorAddressInfo.format = VK_FORMAT_UNDEFINED; - - descriptorInfo.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorInfo.data.pCombinedImageSampler = nullptr; - descriptorInfo.data.pUniformBuffer = &descriptorAddressInfo; - vkGetDescriptorEXT(device, &descriptorInfo, descriptorBufferProperties.uniformBufferDescriptorSize, uniformDescriptorBufPtr); - - // Per-model uniform buffers - for (uint32_t i = 0; i < static_cast(cubes.size()); i++) { - VkDescriptorAddressInfoEXT addr_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT }; - addr_info.address = getBufferDeviceAddress(cubes[i].uniformBuffer.buffer); - addr_info.range = cubes[i].uniformBuffer.size; - addr_info.format = VK_FORMAT_UNDEFINED; - - descriptorInfo.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorInfo.data.pCombinedImageSampler = nullptr; - descriptorInfo.data.pUniformBuffer = &addr_info; - vkGetDescriptorEXT(device, &descriptorInfo, descriptorBufferProperties.uniformBufferDescriptorSize, uniformDescriptorBufPtr + (i + 1) * uniformDescriptor.layoutSize + uniformDescriptor.layoutOffset); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]{}; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - model.bindBuffers(drawCmdBuffers[i]); - - // Descriptor buffer bindings - // Set 0 = uniform buffer - VkDescriptorBufferBindingInfoEXT bindingInfos[2]{}; - bindingInfos[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT; - bindingInfos[0].address = uniformDescriptor.bufferDeviceAddress.deviceAddress; - bindingInfos[0].usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT;// | VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT; - // Set 1 = Image - bindingInfos[1].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT; - bindingInfos[1].pNext = nullptr; - bindingInfos[1].address = combinedImageDescriptor.bufferDeviceAddress.deviceAddress; - bindingInfos[1].usage = VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT | VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT; - vkCmdBindDescriptorBuffersEXT(drawCmdBuffers[i], 2, bindingInfos); - - uint32_t bufferIndexUbo = 0; - VkDeviceSize bufferOffset = 0; - - // Global Matrices (set 0) - bufferOffset = 0; - vkCmdSetDescriptorBufferOffsetsEXT(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &bufferIndexUbo, &bufferOffset); - - // Set and offset into descriptor for each model - for (uint32_t j = 0; j < static_cast(cubes.size()); j++) { - // Uniform buffer (set 1) - // Model ubos start at offset * 1 (slot 0 is global matrices) - bufferOffset = (j + 1) * uniformDescriptor.layoutSize; - vkCmdSetDescriptorBufferOffsetsEXT(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &bufferIndexUbo, &bufferOffset); - // Image (set 2) - uint32_t bufferIndexImage = 1; - bufferOffset = j * combinedImageDescriptor.layoutSize; - vkCmdSetDescriptorBufferOffsetsEXT(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 2, 1, &bufferIndexImage, &bufferOffset); - model.draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - model.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - cubes[0].texture.loadFromFile(getAssetPath() + "textures/crate01_color_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - cubes[1].texture.loadFromFile(getAssetPath() + "textures/crate02_color_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void prepareUniformBuffers() - { - // UBO for camera matrices - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBufferCamera, - sizeof(glm::mat4) * 2)); - VK_CHECK_RESULT(uniformBufferCamera.map()); - - // UBOs for model matrices - for (uint32_t i = 0; i < static_cast(cubes.size()); i++) { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &cubes[i].uniformBuffer, - sizeof(glm::mat4))); - VK_CHECK_RESULT(cubes[i].uniformBuffer.map()); - } - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - memcpy(uniformBufferCamera.mapped, &camera.matrices.perspective, sizeof(glm::mat4)); - memcpy((char*)uniformBufferCamera.mapped + sizeof(glm::mat4), &camera.matrices.view, sizeof(glm::mat4)); - - cubes[0].matrix = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 0.0f, 0.0f)); - cubes[1].matrix = glm::translate(glm::mat4(1.0f), glm::vec3( 1.5f, 0.5f, 0.0f)); - - for (auto& cube : cubes) { - cube.matrix = glm::rotate(cube.matrix, glm::radians(cube.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); - cube.matrix = glm::rotate(cube.matrix, glm::radians(cube.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - cube.matrix = glm::rotate(cube.matrix, glm::radians(cube.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); - cube.matrix = glm::scale(cube.matrix, glm::vec3(0.25f)); - memcpy(cube.uniformBuffer.mapped, &cube.matrix, sizeof(glm::mat4)); - } - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - - vkGetBufferDeviceAddressKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR")); - - vkGetDescriptorSetLayoutSizeEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetDescriptorSetLayoutSizeEXT")); - vkGetDescriptorSetLayoutBindingOffsetEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetDescriptorSetLayoutBindingOffsetEXT")); - vkCmdBindDescriptorBuffersEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBindDescriptorBuffersEXT")); - vkGetDescriptorEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetDescriptorEXT")); - vkCmdBindDescriptorBufferEmbeddedSamplersEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBindDescriptorBufferEmbeddedSamplersEXT")); - vkCmdSetDescriptorBufferOffsetsEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetDescriptorBufferOffsetsEXT")); - - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - prepareDescriptorBuffer(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (animate && !paused) { - cubes[0].rotation.x += 2.5f * frameTimer; - if (cubes[0].rotation.x > 360.0f) - cubes[0].rotation.x -= 360.0f; - cubes[1].rotation.y += 2.0f * frameTimer; - if (cubes[1].rotation.y > 360.0f) - cubes[1].rotation.y -= 360.0f; - } - if ((camera.updated) || (animate && !paused)) { - updateUniformBuffers(); - } - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->checkBox("Animate", &animate); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/descriptorindexing/descriptorindexing.cpp b/examples/descriptorindexing/descriptorindexing.cpp deleted file mode 100644 index 79e6f794..00000000 --- a/examples/descriptorindexing/descriptorindexing.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* -* Vulkan Example - Descriptor indexing (VK_EXT_descriptor_indexing) -* -* Demonstrates use of descriptor indexing to dynamically index into a variable sized array of images -* -* The sample renders multiple objects with the index of the texture (descriptor) to use passed as a vertex attribute (aka "descriptor indexing") -* -* Relevant code parts are marked with [POI] -* -* Copyright (C) 2021-2025 Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - - -#include "vulkanexamplebase.h" - - -class VulkanExample : public VulkanExampleBase -{ -public: - // We will be dynamically indexing into an array of images - std::vector textures; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount{ 0 }; - - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VkPhysicalDeviceDescriptorIndexingFeaturesEXT physicalDeviceDescriptorIndexingFeatures{}; - - struct Vertex { - float pos[3]; - float uv[2]; - int32_t textureIndex; - }; - - VulkanExample() : VulkanExampleBase() - { - title = "Descriptor indexing"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -10.0f)); - camera.setRotation(glm::vec3(-35.0f, 0.0f, 0.0f)); - camera.setPerspective(45.0f, (float)width / (float)height, 0.1f, 256.0f); - - // [POI] Enable required extensions - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - - // [POI] Enable required extension features - physicalDeviceDescriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; - physicalDeviceDescriptorIndexingFeatures.shaderSampledImageArrayNonUniformIndexing = VK_TRUE; - physicalDeviceDescriptorIndexingFeatures.runtimeDescriptorArray = VK_TRUE; - physicalDeviceDescriptorIndexingFeatures.descriptorBindingVariableDescriptorCount = VK_TRUE; - - deviceCreatepNextChain = &physicalDeviceDescriptorIndexingFeatures; - -#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) - // Use layer settings extension to configure MoltenVK - enabledInstanceExtensions.push_back(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME); - - // Configure MoltenVK to use Metal argument buffers (needed for descriptor indexing) - VkLayerSettingEXT layerSetting; - layerSetting.pLayerName = "MoltenVK"; - layerSetting.pSettingName = "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS"; - layerSetting.type = VK_LAYER_SETTING_TYPE_BOOL32_EXT; - layerSetting.valueCount = 1; - - // Make this static so layer setting reference remains valid after leaving constructor scope - static const VkBool32 layerSettingOn = VK_TRUE; - layerSetting.pValues = &layerSettingOn; - enabledLayerSettings.push_back(layerSetting); -#endif - } - - ~VulkanExample() - { - if (device) { - for (auto& texture : textures) { - texture.destroy(); - } - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vertexBuffer.destroy(); - indexBuffer.destroy(); - uniformBuffer.destroy(); - } - } - - // Generate some random textures - void generateTextures() - { - textures.resize(32); - for (size_t i = 0; i < textures.size(); i++) { - std::random_device rndDevice; - std::default_random_engine rndEngine(benchmark.active ? 0 : rndDevice()); - std::uniform_int_distribution<> rndDist(50, UCHAR_MAX); - const int32_t dim = 3; - const size_t bufferSize = dim * dim * 4; - std::vector texture(bufferSize); - for (size_t j = 0; j < dim * dim; j++) { - texture[j * 4] = rndDist(rndEngine); - texture[j * 4 + 1] = rndDist(rndEngine); - texture[j * 4 + 2] = rndDist(rndEngine); - texture[j * 4 + 3] = 255; - } - textures[i].fromBuffer(texture.data(), bufferSize, VK_FORMAT_R8G8B8A8_UNORM, dim, dim, vulkanDevice, queue, VK_FILTER_NEAREST); - } - } - - // Generates a line of cubes with randomized per-face texture indices and uploads them to the GPU - void generateCubes() - { - std::vector vertices; - std::vector indices; - - // Generate random per-face texture indices - std::random_device rndDevice; - std::default_random_engine rndEngine(benchmark.active ? 0 : rndDevice()); - std::uniform_int_distribution rndDist(0, static_cast(textures.size()) - 1); - - // Generate cubes with random per-face texture indices - const uint32_t count = 5; - for (uint32_t i = 0; i < count; i++) { - // Push indices to buffer - const std::vector cubeIndices = { - 0,1,2,0,2,3, - 4,5,6,4,6,7, - 8,9,10,8,10,11, - 12,13,14,12,14,15, - 16,17,18,16,18,19, - 20,21,22,20,22,23 - }; - for (auto& index : cubeIndices) { - indices.push_back(index + static_cast(vertices.size())); - } - // Get random per-Face texture indices that the shader will sample from - int32_t textureIndices[6]; - for (uint32_t j = 0; j < 6; j++) { - textureIndices[j] = rndDist(rndEngine); - } - // Push vertices to buffer - float pos = 2.5f * i - (count * 2.5f / 2.0f) + 1.25f; - const std::vector cube = { - { { -1.0f + pos, -1.0f, 1.0f }, { 0.0f, 0.0f }, textureIndices[0] }, - { { 1.0f + pos, -1.0f, 1.0f }, { 1.0f, 0.0f }, textureIndices[0] }, - { { 1.0f + pos, 1.0f, 1.0f }, { 1.0f, 1.0f }, textureIndices[0] }, - { { -1.0f + pos, 1.0f, 1.0f }, { 0.0f, 1.0f }, textureIndices[0] }, - - { { 1.0f + pos, 1.0f, 1.0f }, { 0.0f, 0.0f }, textureIndices[1] }, - { { 1.0f + pos, 1.0f, -1.0f }, { 1.0f, 0.0f }, textureIndices[1] }, - { { 1.0f + pos, -1.0f, -1.0f }, { 1.0f, 1.0f }, textureIndices[1] }, - { { 1.0f + pos, -1.0f, 1.0f }, { 0.0f, 1.0f }, textureIndices[1] }, - - { { -1.0f + pos, -1.0f, -1.0f }, { 0.0f, 0.0f }, textureIndices[2] }, - { { 1.0f + pos, -1.0f, -1.0f }, { 1.0f, 0.0f }, textureIndices[2] }, - { { 1.0f + pos, 1.0f, -1.0f }, { 1.0f, 1.0f }, textureIndices[2] }, - { { -1.0f + pos, 1.0f, -1.0f }, { 0.0f, 1.0f }, textureIndices[2] }, - - { { -1.0f + pos, -1.0f, -1.0f }, { 0.0f, 0.0f }, textureIndices[3] }, - { { -1.0f + pos, -1.0f, 1.0f }, { 1.0f, 0.0f }, textureIndices[3] }, - { { -1.0f + pos, 1.0f, 1.0f }, { 1.0f, 1.0f }, textureIndices[3] }, - { { -1.0f + pos, 1.0f, -1.0f }, { 0.0f, 1.0f }, textureIndices[3] }, - - { { 1.0f + pos, 1.0f, 1.0f }, { 0.0f, 0.0f }, textureIndices[4] }, - { { -1.0f + pos, 1.0f, 1.0f }, { 1.0f, 0.0f }, textureIndices[4] }, - { { -1.0f + pos, 1.0f, -1.0f }, { 1.0f, 1.0f }, textureIndices[4] }, - { { 1.0f + pos, 1.0f, -1.0f }, { 0.0f, 1.0f }, textureIndices[4] }, - - { { -1.0f + pos, -1.0f, -1.0f }, { 0.0f, 0.0f }, textureIndices[5] }, - { { 1.0f + pos, -1.0f, -1.0f }, { 1.0f, 0.0f }, textureIndices[5] }, - { { 1.0f + pos, -1.0f, 1.0f }, { 1.0f, 1.0f }, textureIndices[5] }, - { { -1.0f + pos, -1.0f, 1.0f }, { 0.0f, 1.0f }, textureIndices[5] }, - }; - for (auto& vertex : cube) { - vertices.push_back(vertex); - } - } - - indexCount = static_cast(indices.size()); - - // Create buffers and upload data to the GPU - struct StagingBuffers { - vks::Buffer vertices; - vks::Buffer indices; - } stagingBuffers; - - // Host visible source buffers (staging) - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.vertices, vertices.size() * sizeof(Vertex), vertices.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.indices, indices.size() * sizeof(uint32_t), indices.data())); - - // Device local destination buffers - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &vertexBuffer, vertices.size() * sizeof(Vertex))); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &indexBuffer, indices.size() * sizeof(uint32_t))); - - // Copy from host do device - vulkanDevice->copyBuffer(&stagingBuffers.vertices, &vertexBuffer, queue); - vulkanDevice->copyBuffer(&stagingBuffers.indices, &indexBuffer, queue); - - // Clean up - stagingBuffers.vertices.destroy(); - stagingBuffers.indices.destroy(); - } - - // [POI] Set up descriptor sets and set layout - void setupDescriptors() - { - // Descriptor pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(textures.size())) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); -#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) - // Increase the per-stage descriptor samplers limit on macOS/iOS (maxPerStageDescriptorUpdateAfterBindSamplers > maxPerStageDescriptorSamplers) - descriptorPoolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; -#endif - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor set layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // [POI] Binding 1 contains a texture array that is dynamically non-uniform sampled from in the fragment shader: - // outFragColor = texture(textures[nonuniformEXT(inTexIndex)], inUV); - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1, static_cast(textures.size())) - }; - - // [POI] The fragment shader will be using an unsized array of samplers, which has to be marked with the VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT - VkDescriptorSetLayoutBindingFlagsCreateInfoEXT setLayoutBindingFlags{}; - setLayoutBindingFlags.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT; - setLayoutBindingFlags.bindingCount = 2; - // Binding 0 is the vertex shader uniform buffer, which does not use indexing - // Binding 1 are the fragment shader images, which use indexing - // In the fragment shader: - // layout (set = 0, binding = 1) uniform sampler2D textures[]; - -#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) - // Disable variable descriptor count feature on macOS/iOS until MoltenVK supports this feature when using combined image sampler textures - // Note we are using only 1 descriptor set with a fixed descriptor count/pool size, so we can simply turn off the capability for now - std::vector descriptorBindingFlags = { - 0, - 0 - }; - setLayoutBindingFlags.pBindingFlags = descriptorBindingFlags.data(); - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - // Increase the per-stage descriptor samplers limit on macOS/iOS (maxPerStageDescriptorUpdateAfterBindSamplers > maxPerStageDescriptorSamplers) - descriptorSetLayoutCI.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; - descriptorSetLayoutCI.pNext = &setLayoutBindingFlags; - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout)); - - // [POI] Descriptor sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - allocInfo.pNext = nullptr; -#else - // Enable variable descriptor count feature on platforms other than macOS/iOS - std::vector descriptorBindingFlags = { - 0, - VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT - }; - setLayoutBindingFlags.pBindingFlags = descriptorBindingFlags.data(); - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - descriptorSetLayoutCI.pNext = &setLayoutBindingFlags; - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout)); - - // [POI] Descriptor sets - // We need to provide the descriptor counts for bindings with variable counts using a new structure - std::vector variableDesciptorCounts = { - static_cast(textures.size()) - }; - - VkDescriptorSetVariableDescriptorCountAllocateInfoEXT variableDescriptorCountAllocInfo = {}; - variableDescriptorCountAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT; - variableDescriptorCountAllocInfo.descriptorSetCount = static_cast(variableDesciptorCounts.size()); - variableDescriptorCountAllocInfo.pDescriptorCounts = variableDesciptorCounts.data(); - - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - allocInfo.pNext = &variableDescriptorCountAllocInfo; -#endif - - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - std::vector writeDescriptorSets(2); - - writeDescriptorSets[0] = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor); - - // Image descriptors for the texture array - std::vector textureDescriptors(textures.size()); - for (size_t i = 0; i < textures.size(); i++) { - textureDescriptors[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - textureDescriptors[i].sampler = textures[i].sampler;; - textureDescriptors[i].imageView = textures[i].view; - } - - // [POI] Second and final descriptor is a texture array - // Unlike an array texture, these are adressed like typical arrays - writeDescriptorSets[1] = {}; - writeDescriptorSets[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSets[1].dstBinding = 1; - writeDescriptorSets[1].dstArrayElement = 0; - writeDescriptorSets[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSets[1].descriptorCount = static_cast(textures.size()); - writeDescriptorSets[1].pBufferInfo = 0; - writeDescriptorSets[1].dstSet = descriptorSet; - writeDescriptorSets[1].pImageInfo = textureDescriptors.data(); - - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - // Vertex bindings and attributes - VkVertexInputBindingDescription vertexInputBinding = { 0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX }; - std::vector vertexInputAttributes = { - { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos) }, - { 1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv) }, - { 2, 0, VK_FORMAT_R32_SINT, offsetof(Vertex, textureIndex) } - }; - VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputStateCI.vertexBindingDescriptionCount = 1; - vertexInputStateCI.pVertexBindingDescriptions = &vertexInputBinding; - vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - // Instacing pipeline - std::array shaderStages; - - shaderStages[0] = loadShader(getShadersPath() + "descriptorindexing/descriptorindexing.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - // [POI] The fragment shader does non-uniform access into our sampler array, so we need to use nonuniformEXT: texture(textures[nonuniformEXT(inTexIndex)], inUV) in it (see descriptorindexing.frag) - shaderStages[1] = loadShader(getShadersPath() + "descriptorindexing/descriptorindexing.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pVertexInputState = &vertexInputStateCI; - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - updateUniformBuffersCamera(); - } - - void updateUniformBuffersCamera() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.model = glm::mat4(1.0f); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void buildCommandBuffers() - { - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &vertexBuffer.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); - drawUI(drawCmdBuffers[i]); - vkCmdEndRenderPass(drawCmdBuffers[i]); - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void prepare() - { - VulkanExampleBase::prepare(); - generateTextures(); - generateCubes(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffersCamera(); - draw(); - } - -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/descriptorsets/descriptorsets.cpp b/examples/descriptorsets/descriptorsets.cpp deleted file mode 100644 index 0efbb4a7..00000000 --- a/examples/descriptorsets/descriptorsets.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* -* Vulkan Example - Using descriptor sets for passing data to shader stages -* -* Relevant code parts are marked with [POI] -* -* Copyright (C) 2018-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - - -class VulkanExample : public VulkanExampleBase -{ -public: - bool animate = true; - - struct Cube { - struct Matrices { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - } matrices; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - vks::Texture2D texture; - vks::Buffer uniformBuffer; - glm::vec3 rotation{ 0.0f }; - }; - std::array cubes; - - vkglTF::Model model; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Using descriptor Sets"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -5.0f)); - } - - ~VulkanExample() - { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - for (auto cube : cubes) { - cube.uniformBuffer.destroy(); - cube.texture.destroy(); - } - } - - virtual void getEnabledFeatures() - { - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - }; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - model.bindBuffers(drawCmdBuffers[i]); - - /* - [POI] Render cubes with separate descriptor sets - */ - for (auto cube : cubes) { - // Bind the cube's descriptor set. This tells the command buffer to use the uniform buffer and image set for this cube - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &cube.descriptorSet, 0, nullptr); - model.draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - model.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - cubes[0].texture.loadFromFile(getAssetPath() + "textures/crate01_color_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - cubes[1].texture.loadFromFile(getAssetPath() + "textures/crate02_color_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - /* - [POI] Set up descriptor sets and set layout - */ - void setupDescriptors() - { - /* - - Descriptor set layout - - The layout describes the shader bindings and types used for a certain descriptor layout and as such must match the shader bindings - - Shader bindings used in this example: - - VS: - layout (set = 0, binding = 0) uniform UBOMatrices ... - - FS : - layout (set = 0, binding = 1) uniform sampler2D ...; - - */ - - std::array setLayoutBindings{}; - - /* - Binding 0: Uniform buffers (used to pass matrices) - */ - setLayoutBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - // Shader binding point - setLayoutBindings[0].binding = 0; - // Accessible from the vertex shader only (flags can be combined to make it accessible to multiple shader stages) - setLayoutBindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - // Binding contains one element (can be used for array bindings) - setLayoutBindings[0].descriptorCount = 1; - - /* - Binding 1: Combined image sampler (used to pass per object texture information) - */ - setLayoutBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - setLayoutBindings[1].binding = 1; - // Accessible from the fragment shader only - setLayoutBindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - setLayoutBindings[1].descriptorCount = 1; - - // Create the descriptor set layout - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI{}; - descriptorLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptorLayoutCI.bindingCount = static_cast(setLayoutBindings.size()); - descriptorLayoutCI.pBindings = setLayoutBindings.data(); - - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayout)); - - /* - - Descriptor pool - - Actual descriptors are allocated from a descriptor pool telling the driver what types and how many - descriptors this application will use - - An application can have multiple pools (e.g. for multiple threads) with any number of descriptor types - as long as device limits are not surpassed - - It's good practice to allocate pools with actually required descriptor types and counts - - */ - - std::array descriptorPoolSizes{}; - - // Uniform buffers : 1 per object - descriptorPoolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorPoolSizes[0].descriptorCount = static_cast(cubes.size()); - - // Combined image samples : 1 per object texture - descriptorPoolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorPoolSizes[1].descriptorCount = static_cast(cubes.size()); - - // Create the global descriptor pool - VkDescriptorPoolCreateInfo descriptorPoolCI = {}; - descriptorPoolCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - descriptorPoolCI.poolSizeCount = static_cast(descriptorPoolSizes.size()); - descriptorPoolCI.pPoolSizes = descriptorPoolSizes.data(); - // Max. number of descriptor sets that can be allocated from this pool (one per object) - descriptorPoolCI.maxSets = static_cast(cubes.size()); - - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorPool)); - - /* - - Descriptor sets - - Using the shared descriptor set layout and the descriptor pool we will now allocate the descriptor sets. - - Descriptor sets contain the actual descriptor for the objects (buffers, images) used at render time. - - */ - - for (auto &cube: cubes) { - - // Allocates an empty descriptor set without actual descriptors from the pool using the set layout - VkDescriptorSetAllocateInfo allocateInfo{}; - allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocateInfo.descriptorPool = descriptorPool; - allocateInfo.descriptorSetCount = 1; - allocateInfo.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocateInfo, &cube.descriptorSet)); - - // Update the descriptor set with the actual descriptors matching shader bindings set in the layout - - std::array writeDescriptorSets{}; - - /* - Binding 0: Object matrices Uniform buffer - */ - writeDescriptorSets[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSets[0].dstSet = cube.descriptorSet; - writeDescriptorSets[0].dstBinding = 0; - writeDescriptorSets[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - writeDescriptorSets[0].pBufferInfo = &cube.uniformBuffer.descriptor; - writeDescriptorSets[0].descriptorCount = 1; - - /* - Binding 1: Object texture - */ - writeDescriptorSets[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSets[1].dstSet = cube.descriptorSet; - writeDescriptorSets[1].dstBinding = 1; - writeDescriptorSets[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - // Images use a different descriptor structure, so we use pImageInfo instead of pBufferInfo - writeDescriptorSets[1].pImageInfo = &cube.texture.descriptor; - writeDescriptorSets[1].descriptorCount = 1; - - // Execute the writes to update descriptors for this set - // Note that it's also possible to gather all writes and only run updates once, even for multiple sets - // This is possible because each VkWriteDescriptorSet also contains the destination set to be updated - // For simplicity we will update once per set instead - - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - } - - void preparePipelines() - { - /* - [POI] Create a pipeline layout used for our graphics pipeline - */ - VkPipelineLayoutCreateInfo pipelineLayoutCI{}; - pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - // The pipeline layout is based on the descriptor set layout we created above - pipelineLayoutCI.setLayoutCount = 1; - pipelineLayoutCI.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()),0); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color}); - - shaderStages[0] = loadShader(getShadersPath() + "descriptorsets/cube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "descriptorsets/cube.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareUniformBuffers() - { - // Vertex shader matrix uniform buffer block - for (auto& cube : cubes) { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &cube.uniformBuffer, - sizeof(Cube::Matrices))); - VK_CHECK_RESULT(cube.uniformBuffer.map()); - } - - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - cubes[0].matrices.model = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 0.0f, 0.0f)); - cubes[1].matrices.model = glm::translate(glm::mat4(1.0f), glm::vec3( 1.5f, 0.5f, 0.0f)); - - for (auto& cube : cubes) { - cube.matrices.projection = camera.matrices.perspective; - cube.matrices.view = camera.matrices.view; - cube.matrices.model = glm::rotate(cube.matrices.model, glm::radians(cube.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); - cube.matrices.model = glm::rotate(cube.matrices.model, glm::radians(cube.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - cube.matrices.model = glm::rotate(cube.matrices.model, glm::radians(cube.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); - cube.matrices.model = glm::scale(cube.matrices.model, glm::vec3(0.25f)); - memcpy(cube.uniformBuffer.mapped, &cube.matrices, sizeof(cube.matrices)); - } - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (animate && !paused) { - cubes[0].rotation.x += 2.5f * frameTimer; - if (cubes[0].rotation.x > 360.0f) - cubes[0].rotation.x -= 360.0f; - cubes[1].rotation.y += 2.0f * frameTimer; - if (cubes[1].rotation.y > 360.0f) - cubes[1].rotation.y -= 360.0f; - } - if ((camera.updated) || (animate && !paused)) { - updateUniformBuffers(); - } - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->checkBox("Animate", &animate); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/displacement/displacement.cpp b/examples/displacement/displacement.cpp deleted file mode 100644 index 6a9e2ac4..00000000 --- a/examples/displacement/displacement.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/* -* Vulkan Example - Displacement mapping with tessellation shaders -* -* This samples uses tessellation shaders to displace geometry based on a height map -* -* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - - -class VulkanExample : public VulkanExampleBase -{ -public: - bool splitScreen = true; - bool displacement = true; - - vkglTF::Model plane; - vks::Texture2D colorHeightMap; - - // Uniform data/buffer used by both tessellation shader stages - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 lightPos = glm::vec4(0.0f, -1.0f, 0.0f, 0.0f); - float tessAlpha = 1.0f; - float tessStrength = 0.1f; - float tessLevel = 64.0f; - } uniformData; - vks::Buffer uniformBuffer; - - struct Pipelines { - VkPipeline solid{ VK_NULL_HANDLE }; - VkPipeline wireframe{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Tessellation shader displacement"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -1.25f)); - camera.setRotation(glm::vec3(-20.0f, 45.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.solid, nullptr); - if (pipelines.wireframe != VK_NULL_HANDLE) { - vkDestroyPipeline(device, pipelines.wireframe, nullptr); - }; - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - colorHeightMap.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Tessellation shader support is required for this example - if (deviceFeatures.tessellationShader) { - enabledFeatures.tessellationShader = VK_TRUE; - } - else { - vks::tools::exitFatal("Selected GPU does not support tessellation shaders!", VK_ERROR_FEATURE_NOT_PRESENT); - } - // Fill mode non solid is required for wireframe display - if (deviceFeatures.fillModeNonSolid) { - enabledFeatures.fillModeNonSolid = VK_TRUE; - } - else { - splitScreen = false; - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - plane.loadFromFile(getAssetPath() + "models/displacement_plane.gltf", vulkanDevice, queue, glTFLoadingFlags); - colorHeightMap.loadFromFile(getAssetPath() + "textures/stonefloor03_color_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(splitScreen ? width / 2 : width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdSetLineWidth(drawCmdBuffers[i], 1.0f); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - plane.bindBuffers(drawCmdBuffers[i]); - - if (splitScreen) - { - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.wireframe); - plane.draw(drawCmdBuffers[i]); - scissor.offset.x = width / 2; - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - } - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solid); - plane.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Tessellation shader ubo - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0), - // Binding 1 : Combined color (rgb) and height (alpha) map - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Tessellation shader ubo - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Color and displacement map (alpha channel) - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &colorHeightMap.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - VkPipelineTessellationStateCreateInfo tessellationState = vks::initializers::pipelineTessellationStateCreateInfo(3); - - // Load shaders - std::array shaderStages; - shaderStages[0] = loadShader(getShadersPath() + "displacement/base.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "displacement/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - shaderStages[2] = loadShader(getShadersPath() + "displacement/displacement.tesc.spv", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); - shaderStages[3] = loadShader(getShadersPath() + "displacement/displacement.tese.spv", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.pTessellationState = &tessellationState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - // Tessellation pipelines - // Solid pipeline - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.solid)); - if (deviceFeatures.fillModeNonSolid) { - // Wireframe pipeline - rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; - rasterizationState.cullMode = VK_CULL_MODE_NONE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); - } - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Tessellation evaluation shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - uniformData.lightPos.y = -0.5f - uniformData.tessStrength; - // Tessellation control - float savedLevel = uniformData.tessLevel; - // If displacement is unchecked, we simply set the tessellation level to 1.0f, which disables tessellation - if (!displacement) { - uniformData.tessLevel = 1.0f; - } - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - if (!displacement) { - uniformData.tessLevel = savedLevel; - } - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->checkBox("Tessellation displacement", &displacement)) { - updateUniformBuffers(); - } - if (overlay->inputFloat("Strength", &uniformData.tessStrength, 0.025f, 3)) { - updateUniformBuffers(); - } - if (overlay->inputFloat("Level", &uniformData.tessLevel, 0.5f, 2)) { - updateUniformBuffers(); - } - if (deviceFeatures.fillModeNonSolid) { - if (overlay->checkBox("Splitscreen", &splitScreen)) { - buildCommandBuffers(); - updateUniformBuffers(); - } - } - - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/distancefieldfonts/distancefieldfonts.cpp b/examples/distancefieldfonts/distancefieldfonts.cpp deleted file mode 100644 index d484fcca..00000000 --- a/examples/distancefieldfonts/distancefieldfonts.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/* -* Vulkan Example - Font rendering using signed distance fields -* -* This sample compares rendering resolution independent fonts using signed distance fields to traditional bitmap fonts -* -* Font generated using https://github.com/libgdx/libgdx/wiki/Hiero -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -// Vertex layout for this example -struct Vertex { - float pos[3]; - float uv[2]; -}; - -// AngelCode .fnt format structs and classes -struct bmchar { - uint32_t x, y; - uint32_t width; - uint32_t height; - int32_t xoffset; - int32_t yoffset; - int32_t xadvance; - uint32_t page; -}; - -// Quick and dirty : We store complete ASCII table -// Only chars present in the .fnt are filled with data, so not a complete, production ready solution! -std::array fontChars; - -int32_t nextValuePair(std::stringstream *stream) -{ - std::string pair; - *stream >> pair; - size_t spos = pair.find("="); - std::string value = pair.substr(spos + 1); - int32_t val = std::stoi(value); - return val; -} - -class VulkanExample : public VulkanExampleBase -{ -public: - bool splitScreen = true; - - struct Textures { - vks::Texture2D fontSDF; - vks::Texture2D fontBitmap; - } textures; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount{ 0 }; - - struct UniformData { - // Scene matrices - glm::mat4 projection; - glm::mat4 modelView; - // Font display options - glm::vec4 outlineColor{ 1.0f, 0.0f, 0.0f, 0.0f }; - float outlineWidth{ 0.6f }; - float outline{ true }; - } uniformData; - vks::Buffer uniformBuffer; - - struct Pipelines { - VkPipeline sdf{ VK_NULL_HANDLE }; - VkPipeline bitmap{ VK_NULL_HANDLE }; - } pipelines; - - struct DescriptorSets { - VkDescriptorSet sdf{ VK_NULL_HANDLE }; - VkDescriptorSet bitmap{ VK_NULL_HANDLE }; - } descriptorSets; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Distance field font rendering"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -2.0f)); - camera.setRotation(glm::vec3(0.0f)); - camera.setPerspective(splitScreen ? 30.0f : 45.0f, (float)width / (float)(height * ((splitScreen) ? 0.5f : 1.0f)), 1.0f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - textures.fontSDF.destroy(); - textures.fontBitmap.destroy(); - vkDestroyPipeline(device, pipelines.sdf, nullptr); - vkDestroyPipeline(device, pipelines.bitmap, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vertexBuffer.destroy(); - indexBuffer.destroy(); - uniformBuffer.destroy(); - } - } - - // Basic parser for AngelCode bitmap font format files - // See http://www.angelcode.com/products/bmfont/doc/file_format.html for details - void parsebmFont() - { - std::string fileName = getAssetPath() + "font.fnt"; - -#if defined(__ANDROID__) - // Font description file is stored inside the apk - // So we need to load it using the asset manager - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, fileName.c_str(), AASSET_MODE_STREAMING); - assert(asset); - size_t size = AAsset_getLength(asset); - - assert(size > 0); - - void *fileData = malloc(size); - AAsset_read(asset, fileData, size); - AAsset_close(asset); - - std::stringbuf sbuf((const char*)fileData); - std::istream istream(&sbuf); -#else - std::filebuf fileBuffer; - fileBuffer.open(fileName, std::ios::in); - std::istream istream(&fileBuffer); -#endif - - assert(istream.good()); - - while (!istream.eof()) - { - std::string line; - std::stringstream lineStream; - std::getline(istream, line); - lineStream << line; - - std::string info; - lineStream >> info; - - if (info == "char") - { - // char id - uint32_t charid = nextValuePair(&lineStream); - // Char properties - fontChars[charid].x = nextValuePair(&lineStream); - fontChars[charid].y = nextValuePair(&lineStream); - fontChars[charid].width = nextValuePair(&lineStream); - fontChars[charid].height = nextValuePair(&lineStream); - fontChars[charid].xoffset = nextValuePair(&lineStream); - fontChars[charid].yoffset = nextValuePair(&lineStream); - fontChars[charid].xadvance = nextValuePair(&lineStream); - fontChars[charid].page = nextValuePair(&lineStream); - } - } - - } - - void loadAssets() - { - textures.fontSDF.loadFromFile(getAssetPath() + "textures/font_sdf_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.fontBitmap.loadFromFile(getAssetPath() + "textures/font_bitmap_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (splitScreen) ? (float)height / 2.0f : (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - - // Signed distance field font - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.sdf, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.sdf); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &vertexBuffer.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); - - // Linear filtered bitmap font - if (splitScreen) - { - viewport.y = (float)height / 2.0f; - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.bitmap, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.bitmap); - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - // Creates a vertex and index buffer with triangle data containing the chars of the given text - void generateText(std:: string text) - { - std::vector vertices; - std::vector indices; - uint32_t indexOffset = 0; - - float w = static_cast(textures.fontSDF.width); - - float posx = 0.0f; - float posy = 0.0f; - - for (uint32_t i = 0; i < text.size(); i++) - { - bmchar *charInfo = &fontChars[(int)text[i]]; - - if (charInfo->width == 0) - charInfo->width = 36; - - float charw = ((float)(charInfo->width) / 36.0f); - float dimx = 1.0f * charw; - float charh = ((float)(charInfo->height) / 36.0f); - float dimy = 1.0f * charh; - - float us = charInfo->x / w; - float ue = (charInfo->x + charInfo->width) / w; - float ts = charInfo->y / w; - float te = (charInfo->y + charInfo->height) / w; - - float xo = charInfo->xoffset / 36.0f; - float yo = charInfo->yoffset / 36.0f; - - posy = yo; - - vertices.push_back({ { posx + dimx + xo, posy + dimy, 0.0f }, { ue, te } }); - vertices.push_back({ { posx + xo, posy + dimy, 0.0f }, { us, te } }); - vertices.push_back({ { posx + xo, posy, 0.0f }, { us, ts } }); - vertices.push_back({ { posx + dimx + xo, posy, 0.0f }, { ue, ts } }); - - std::array letterIndices = { 0,1,2, 2,3,0 }; - for (auto& index : letterIndices) - { - indices.push_back(indexOffset + index); - } - indexOffset += 4; - - float advance = ((float)(charInfo->xadvance) / 36.0f); - posx += advance; - } - indexCount = static_cast(indices.size()); - - // Center - for (auto& v : vertices) - { - v.pos[0] -= posx / 2.0f; - v.pos[1] -= 0.5f; - } - - // Generate host accessible buffers for the text vertices and indices and upload the data - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &vertexBuffer, vertices.size() * sizeof(Vertex), vertices.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &indexBuffer, indices.size() * sizeof(uint32_t), indices.data())); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - - // The pipeline uses one set and three bindings - // Binding 0 : Shader uniform buffer - // Binding 1 : Fragment shader image sampler - - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - // Signed distance font descriptor set - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.sdf)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.sdf, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.sdf, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.fontSDF.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Bitmap font descriptor set - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.bitmap)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.bitmap, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.bitmap, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.fontBitmap.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_TRUE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Enabled blending (With the background) - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - - // Vertex input state - std::vector vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX) - }; - std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)), - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)), - }; - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &vertexInputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - - // Signed distance font rendering pipeline - shaderStages[0] = loadShader(getShadersPath() + "distancefieldfonts/sdf.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "distancefieldfonts/sdf.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.sdf)); - - // Bitmap font rendering pipeline - shaderStages[0] = loadShader(getShadersPath() + "distancefieldfonts/bitmap.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "distancefieldfonts/bitmap.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.bitmap)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - // Adjust camera perspective as we render two viewports - camera.setPerspective(splitScreen ? 30.0f : 45.0f, (float)width / (float)(height * ((splitScreen) ? 0.5f : 1.0f)), 1.0f, 256.0f); - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - parsebmFont(); - loadAssets(); - generateText("Vulkan"); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - bool outline = (uniformData.outline == 1.0f); - if (overlay->checkBox("Outline", &outline)) { - uniformData.outline = outline ? 1.0f : 0.0f; - } - if (overlay->checkBox("Splitscreen", &splitScreen)) { - camera.setPerspective(splitScreen ? 30.0f : 45.0f, (float)width / (float)(height * ((splitScreen) ? 0.5f : 1.0f)), 1.0f, 256.0f); - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/dynamicrendering/dynamicrendering.cpp b/examples/dynamicrendering/dynamicrendering.cpp deleted file mode 100644 index b3ac9ebc..00000000 --- a/examples/dynamicrendering/dynamicrendering.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Vulkan Example - Using VK_KHR_dynamic_rendering for rendering without framebuffers and render passes - * - * Copyright (C) 2022-2023 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - - -class VulkanExample : public VulkanExampleBase -{ -public: - PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR{ VK_NULL_HANDLE }; - PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR{ VK_NULL_HANDLE }; - - VkPhysicalDeviceDynamicRenderingFeaturesKHR enabledDynamicRenderingFeaturesKHR{}; - - vkglTF::Model model; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 viewPos; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Dynamic rendering"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -10.0f)); - camera.setRotation(glm::vec3(-7.5f, 72.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - - // The sample uses the extension (instead of Vulkan 1.2, where dynamic rendering is core) - enabledDeviceExtensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME); - - // in addition to the extension, the feature needs to be explicitly enabled too by chaining the extension structure into device creation - enabledDynamicRenderingFeaturesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR; - enabledDynamicRenderingFeaturesKHR.dynamicRendering = VK_TRUE; - - deviceCreatepNextChain = &enabledDynamicRenderingFeaturesKHR; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - void setupRenderPass() - { - // With VK_KHR_dynamic_rendering we no longer need a render pass, so skip the sample base render pass setup - renderPass = VK_NULL_HANDLE; - } - - void setupFrameBuffer() - { - // With VK_KHR_dynamic_rendering we no longer need a frame buffer, so skip the sample base framebuffer setup - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - }; - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - model.loadFromFile(getAssetPath() + "models/voyager.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // With dynamic rendering there are no subpass dependencies, so we need to take care of proper layout transitions by using barriers - // This set of barriers prepares the color and depth images for output - vks::tools::insertImageMemoryBarrier( - drawCmdBuffers[i], - swapChain.images[i], - 0, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - vks::tools::insertImageMemoryBarrier( - drawCmdBuffers[i], - depthStencil.image, - 0, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1 }); - - // New structures are used to define the attachments used in dynamic rendering - VkRenderingAttachmentInfoKHR colorAttachment{}; - colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; - colorAttachment.imageView = swapChain.imageViews[i]; - colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.clearValue.color = { 0.0f,0.0f,0.0f,0.0f }; - - // A single depth stencil attachment info can be used, but they can also be specified separately. - // When both are specified separately, the only requirement is that the image view is identical. - VkRenderingAttachmentInfoKHR depthStencilAttachment{}; - depthStencilAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; - depthStencilAttachment.imageView = depthStencil.view; - depthStencilAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - depthStencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - depthStencilAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - depthStencilAttachment.clearValue.depthStencil = { 1.0f, 0 }; - - VkRenderingInfoKHR renderingInfo{}; - renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR; - renderingInfo.renderArea = { 0, 0, width, height }; - renderingInfo.layerCount = 1; - renderingInfo.colorAttachmentCount = 1; - renderingInfo.pColorAttachments = &colorAttachment; - renderingInfo.pDepthAttachment = &depthStencilAttachment; - renderingInfo.pStencilAttachment = &depthStencilAttachment; - - // Begin dynamic rendering - vkCmdBeginRenderingKHR(drawCmdBuffers[i], &renderingInfo); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - model.draw(drawCmdBuffers[i], vkglTF::RenderFlags::BindImages, pipelineLayout); - - drawUI(drawCmdBuffers[i]); - - // End dynamic rendering - vkCmdEndRenderingKHR(drawCmdBuffers[i]); - - // This set of barriers prepares the color image for presentation, we don't need to care for the depth image - vks::tools::insertImageMemoryBarrier( - drawCmdBuffers[i], - swapChain.images[i], - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - 0, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - // Layout - const std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - // Uses set 0 for passing vertex shader ubo and set 1 for fragment shader images (taken from glTF model) - const std::vector setLayouts = { - descriptorSetLayout, - vkglTF::descriptorSetLayoutImage, - }; - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), 2); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages{}; - - // We no longer need to set a renderpass for the pipeline create info - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(); - pipelineCI.layout = pipelineLayout; - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - // New create info to define color, depth and stencil attachments at pipeline create time - VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo{}; - pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; - pipelineRenderingCreateInfo.colorAttachmentCount = 1; - pipelineRenderingCreateInfo.pColorAttachmentFormats = &swapChain.colorFormat; - pipelineRenderingCreateInfo.depthAttachmentFormat = depthFormat; - pipelineRenderingCreateInfo.stencilAttachmentFormat = depthFormat; - // Chain into the pipeline creat einfo - pipelineCI.pNext = &pipelineRenderingCreateInfo; - - shaderStages[0] = loadShader(getShadersPath() + "dynamicrendering/texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "dynamicrendering/texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(uniformData), &uniformData)); - VK_CHECK_RESULT(uniformBuffer.map()); - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - uniformData.viewPos = camera.viewPos; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - - // Since we use an extension, we need to expliclity load the function pointers for extension related Vulkan commands - vkCmdBeginRenderingKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBeginRenderingKHR")); - vkCmdEndRenderingKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdEndRenderingKHR")); - - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/dynamicrenderingmultisampling/dynamicrenderingmultisampling.cpp b/examples/dynamicrenderingmultisampling/dynamicrenderingmultisampling.cpp deleted file mode 100644 index 06971270..00000000 --- a/examples/dynamicrenderingmultisampling/dynamicrenderingmultisampling.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Vulkan Example - Using Multi sampling with VK_KHR_dynamic_rendering - * - * Copyright (C) 2025 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR{ VK_NULL_HANDLE }; - PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR{ VK_NULL_HANDLE }; - - VkPhysicalDeviceDynamicRenderingFeaturesKHR enabledDynamicRenderingFeaturesKHR{}; - - vkglTF::Model model; - - const VkSampleCountFlagBits multiSampleCount = VK_SAMPLE_COUNT_4_BIT; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 viewPos; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - // Intermediate images used for multi sampling - struct Image { - VkImage image{ VK_NULL_HANDLE }; - VkImageView view{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - }; - Image renderImage; - - VulkanExample() : VulkanExampleBase() - { - title = "Multi sampling with dynamic rendering"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -10.0f)); - camera.setRotation(glm::vec3(-7.5f, 72.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - settings.overlay = false; - - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - - // The sample uses the extension (instead of Vulkan 1.2, where dynamic rendering is core) - enabledDeviceExtensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME); - - // in addition to the extension, the feature needs to be explicitly enabled too by chaining the extension structure into device creation - enabledDynamicRenderingFeaturesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR; - enabledDynamicRenderingFeaturesKHR.dynamicRendering = VK_TRUE; - - deviceCreatepNextChain = &enabledDynamicRenderingFeaturesKHR; - } - - ~VulkanExample() override - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - vkDestroyImage(device, renderImage.image, nullptr); - vkDestroyImageView(device, renderImage.view, nullptr); - vkFreeMemory(device, renderImage.memory, nullptr); - } - } - - void setupRenderPass() override - { - // With VK_KHR_dynamic_rendering we no longer need a render pass, so we can skip the sample base render pass setup - renderPass = VK_NULL_HANDLE; - } - - void setupFrameBuffer() override - { - // With VK_KHR_dynamic_rendering we no longer need a frame buffer, so we can so skip the sample base framebuffer setup - // For multi sampling we need intermediate images that are then resolved to the final presentation image - vkDestroyImage(device, renderImage.image, nullptr); - vkDestroyImageView(device, renderImage.view, nullptr); - vkFreeMemory(device, renderImage.memory, nullptr); - VkImageCreateInfo renderImageCI = vks::initializers::imageCreateInfo(); - renderImageCI.imageType = VK_IMAGE_TYPE_2D; - renderImageCI.format = swapChain.colorFormat; - renderImageCI.extent = { width, height, 1 }; - renderImageCI.mipLevels = 1; - renderImageCI.arrayLayers = 1; - renderImageCI.samples = multiSampleCount; - renderImageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - renderImageCI.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - renderImageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK_RESULT(vkCreateImage(device, &renderImageCI, nullptr, &renderImage.image)); - VkMemoryRequirements memReqs{}; - vkGetImageMemoryRequirements(device, renderImage.image, &memReqs); - VkMemoryAllocateInfo memAllloc{}; - memAllloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memAllloc.allocationSize = memReqs.size; - memAllloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllloc, nullptr, &renderImage.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, renderImage.image, renderImage.memory, 0)); - VkImageViewCreateInfo imageViewCI = vks::initializers::imageViewCreateInfo(); - imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageViewCI.image = renderImage.image; - imageViewCI.format = swapChain.colorFormat; - imageViewCI.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - VK_CHECK_RESULT(vkCreateImageView(device, &imageViewCI, nullptr, &renderImage.view)); - } - - // We need to override the default depth/stencil setup to create a depth image that supports multi sampling - void setupDepthStencil() override - { - VkImageCreateInfo imageCI{}; - imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = depthFormat; - imageCI.extent = { width, height, 1 }; - imageCI.mipLevels = 1; - imageCI.arrayLayers = 1; - imageCI.samples = multiSampleCount; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &depthStencil.image)); - VkMemoryRequirements memReqs{}; - vkGetImageMemoryRequirements(device, depthStencil.image, &memReqs); - VkMemoryAllocateInfo memAllloc{}; - memAllloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memAllloc.allocationSize = memReqs.size; - memAllloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllloc, nullptr, &depthStencil.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, depthStencil.image, depthStencil.memory, 0)); - VkImageViewCreateInfo depthImageViewCI{}; - depthImageViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - depthImageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthImageViewCI.image = depthStencil.image; - depthImageViewCI.format = depthFormat; - depthImageViewCI.subresourceRange.baseMipLevel = 0; - depthImageViewCI.subresourceRange.levelCount = 1; - depthImageViewCI.subresourceRange.baseArrayLayer = 0; - depthImageViewCI.subresourceRange.layerCount = 1; - depthImageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - // Stencil aspect should only be set on depth + stencil formats (VK_FORMAT_D16_UNORM_S8_UINT..VK_FORMAT_D32_SFLOAT_S8_UINT - if (depthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) { - depthImageViewCI.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - VK_CHECK_RESULT(vkCreateImageView(device, &depthImageViewCI, nullptr, &depthStencil.view)); - } - - // Enable physical device features required for this example - void getEnabledFeatures() override - { - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - }; - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - model.loadFromFile(getAssetPath() + "models/voyager.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void buildCommandBuffers() override - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // With dynamic rendering there are no subpass dependencies, so we need to take care of proper layout transitions by using barriers - // This set of barriers prepares the color and depth images for output - vks::tools::insertImageMemoryBarrier( - drawCmdBuffers[i], - renderImage.image, - 0, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - vks::tools::insertImageMemoryBarrier( - drawCmdBuffers[i], - depthStencil.image, - 0, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1 }); - - // New structures are used to define the attachments used in dynamic rendering - VkRenderingAttachmentInfoKHR colorAttachment{}; - colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; - colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.clearValue.color = { 0.0f,0.0f,0.0f,0.0f }; - // When multi sampling is used, we use intermediate images to render and resolve to the swap chain images - colorAttachment.imageView = renderImage.view; - colorAttachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; - colorAttachment.resolveImageView = swapChain.imageViews[i]; - colorAttachment.resolveImageLayout = VK_IMAGE_LAYOUT_GENERAL; - - // A single depth stencil attachment info can be used, but they can also be specified separately. - // When both are specified separately, the only requirement is that the image view is identical. - VkRenderingAttachmentInfoKHR depthStencilAttachment{}; - depthStencilAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; - depthStencilAttachment.imageView = depthStencil.view; - depthStencilAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - depthStencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - depthStencilAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - depthStencilAttachment.clearValue.depthStencil = { 1.0f, 0 }; - - VkRenderingInfoKHR renderingInfo{}; - renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR; - renderingInfo.renderArea = { 0, 0, width, height }; - renderingInfo.layerCount = 1; - renderingInfo.colorAttachmentCount = 1; - renderingInfo.pColorAttachments = &colorAttachment; - renderingInfo.pDepthAttachment = &depthStencilAttachment; - renderingInfo.pStencilAttachment = &depthStencilAttachment; - - // Begin dynamic rendering - vkCmdBeginRenderingKHR(drawCmdBuffers[i], &renderingInfo); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - model.draw(drawCmdBuffers[i], vkglTF::RenderFlags::BindImages, pipelineLayout); - - drawUI(drawCmdBuffers[i]); - - // End dynamic rendering - vkCmdEndRenderingKHR(drawCmdBuffers[i]); - - // This set of barriers prepares the color image for presentation, we don't need to care for the depth image - vks::tools::insertImageMemoryBarrier( - drawCmdBuffers[i], - swapChain.images[i], - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - 0, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - // Layout - const std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - // Uses set 0 for passing vertex shader ubo and set 1 for fragment shader images (taken from glTF model) - const std::vector setLayouts = { - descriptorSetLayout, - vkglTF::descriptorSetLayoutImage, - }; - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), 2); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(multiSampleCount, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages{}; - - // We no longer need to set a renderpass for the pipeline create info - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(); - pipelineCI.layout = pipelineLayout; - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - // New create info to define color, depth and stencil attachments at pipeline create time - VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo{}; - pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; - pipelineRenderingCreateInfo.colorAttachmentCount = 1; - pipelineRenderingCreateInfo.pColorAttachmentFormats = &swapChain.colorFormat; - pipelineRenderingCreateInfo.depthAttachmentFormat = depthFormat; - pipelineRenderingCreateInfo.stencilAttachmentFormat = depthFormat; - // Chain into the pipeline creat einfo - pipelineCI.pNext = &pipelineRenderingCreateInfo; - - shaderStages[0] = loadShader(getShadersPath() + "dynamicrendering/texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "dynamicrendering/texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(uniformData), &uniformData)); - VK_CHECK_RESULT(uniformBuffer.map()); - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - uniformData.viewPos = camera.viewPos; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void prepare() override - { - VulkanExampleBase::prepare(); - - // Since we use an extension, we need to expliclity load the function pointers for extension related Vulkan commands - vkCmdBeginRenderingKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBeginRenderingKHR")); - vkCmdEndRenderingKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdEndRenderingKHR")); - - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void render() override - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/dynamicstate/dynamicstate.cpp b/examples/dynamicstate/dynamicstate.cpp deleted file mode 100644 index a8c200c3..00000000 --- a/examples/dynamicstate/dynamicstate.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* -* Vulkan Example - Using dynamic state -* -* This sample demonstrates the use of some of the VK_EXT_dynamic_state extensions -* These allow an application to set some pipeline related state dynamically at drawtime -* instead of having to pre-bake the state into a pipeline -* This can help reduce the number of pipelines required -* -* Copyright (C) 2022-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample: public VulkanExampleBase -{ -public: - vkglTF::Model scene; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 lightPos{ 0.0f, 2.0f, 1.0f, 0.0f }; - } uniformData; - vks::Buffer uniformBuffer; - - float clearColor[4] = { 0.0f, 0.0f, 0.2f, 1.0f }; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - // This sample demonstrates different dynamic states, so we check and store what extension is available - bool hasDynamicState{ false }; - bool hasDynamicState2{ false }; - bool hasDynamicState3{ false }; - bool hasDynamicVertexState{ false }; - - VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeaturesEXT{}; - VkPhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2FeaturesEXT{}; - VkPhysicalDeviceExtendedDynamicState3FeaturesEXT extendedDynamicState3FeaturesEXT{}; - - // Function pointers for dynamic states used in this sample - // VK_EXT_dynamic_stte - PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{ nullptr }; - PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT{ nullptr }; - PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT{ nullptr }; - PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT{ nullptr }; - // VK_EXT_dynamic_state_2 - PFN_vkCmdSetRasterizerDiscardEnable vkCmdSetRasterizerDiscardEnableEXT{ nullptr }; - // VK_EXT_dynamic_state_3 - PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT{ nullptr }; - PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT{ nullptr }; - - // Dynamic state UI toggles - struct DynamicState { - int32_t cullMode = VK_CULL_MODE_BACK_BIT; - int32_t frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - bool depthTest = true; - bool depthWrite = true; - } dynamicState; - struct DynamicState2 { - bool rasterizerDiscardEnable = false; - } dynamicState2; - struct DynamicState3 { - bool colorBlendEnable = false; - } dynamicState3; - - VulkanExample() : VulkanExampleBase() - { - title = "Dynamic state"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -10.5f)); - camera.setRotation(glm::vec3(-25.0f, 15.0f, 0.0f)); - camera.setRotationSpeed(0.5f); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - - // Note: We enable the dynamic state extensions dynamically, based on which ones the device supports see getEnabledExtensions - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - void getEnabledExtensions() - { - // Get the full list of extended dynamic state features supported by the device - extendedDynamicStateFeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; - extendedDynamicStateFeaturesEXT.pNext = &extendedDynamicState2FeaturesEXT; - extendedDynamicState2FeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT; - extendedDynamicState2FeaturesEXT.pNext = &extendedDynamicState3FeaturesEXT; - extendedDynamicState3FeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT; - extendedDynamicState3FeaturesEXT.pNext = nullptr; - - VkPhysicalDeviceFeatures2 physicalDeviceFeatures2; - physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - physicalDeviceFeatures2.pNext = &extendedDynamicStateFeaturesEXT; - vkGetPhysicalDeviceFeatures2(physicalDevice, &physicalDeviceFeatures2); - - // Check what dynamic states are supported by the current implementation - // Checking for available features is probably sufficient, but retained redundant extension checks for clarity and consistency - hasDynamicState = vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) && extendedDynamicStateFeaturesEXT.extendedDynamicState; - hasDynamicState2 = vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME) && extendedDynamicState2FeaturesEXT.extendedDynamicState2; - hasDynamicState3 = vulkanDevice->extensionSupported(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME) && extendedDynamicState3FeaturesEXT.extendedDynamicState3ColorBlendEnable && extendedDynamicState3FeaturesEXT.extendedDynamicState3ColorBlendEquation; - hasDynamicVertexState = vulkanDevice->extensionSupported(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); - - // Enable dynamic state extensions if present. This function is called after physical and before logical device creation, so we can enabled extensions based on a list of supported extensions - if (hasDynamicState) { - enabledDeviceExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); - extendedDynamicStateFeaturesEXT.pNext = nullptr; - deviceCreatepNextChain = &extendedDynamicStateFeaturesEXT; - } - if (hasDynamicState2) { - enabledDeviceExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); - extendedDynamicState2FeaturesEXT.pNext = nullptr; - if (hasDynamicState) { - extendedDynamicStateFeaturesEXT.pNext = &extendedDynamicState2FeaturesEXT; - } - else { - deviceCreatepNextChain = &extendedDynamicState2FeaturesEXT; - } - } - if (hasDynamicState3) { - enabledDeviceExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); - if (hasDynamicState2) { - extendedDynamicState2FeaturesEXT.pNext = &extendedDynamicState3FeaturesEXT; - } - else { - deviceCreatepNextChain = &extendedDynamicState3FeaturesEXT; - } - - } - if (hasDynamicVertexState) { - enabledDeviceExtensions.push_back(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { clearColor[0], clearColor[1], clearColor[2], clearColor[3] } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Apply dynamic states - - if (vkCmdSetCullModeEXT) { - vkCmdSetCullModeEXT(drawCmdBuffers[i], VkCullModeFlagBits(dynamicState.cullMode)); - } - if (vkCmdSetFrontFaceEXT) { - vkCmdSetFrontFaceEXT(drawCmdBuffers[i], VkFrontFace(dynamicState.frontFace)); - } - if (vkCmdSetDepthTestEnableEXT) { - vkCmdSetDepthTestEnableEXT(drawCmdBuffers[i], VkFrontFace(dynamicState.depthTest)); - } - if (vkCmdSetDepthWriteEnableEXT) { - vkCmdSetDepthWriteEnableEXT(drawCmdBuffers[i], VkFrontFace(dynamicState.depthWrite)); - } - - if (vkCmdSetRasterizerDiscardEnableEXT) { - vkCmdSetRasterizerDiscardEnableEXT(drawCmdBuffers[i], VkBool32(dynamicState2.rasterizerDiscardEnable)); - } - - if (vkCmdSetColorBlendEnableEXT) { - const std::vector blendEnables = { dynamicState3.colorBlendEnable }; - vkCmdSetColorBlendEnableEXT(drawCmdBuffers[i], 0, 1, blendEnables.data()); - - VkColorBlendEquationEXT colorBlendEquation{}; - - if (dynamicState3.colorBlendEnable) { - colorBlendEquation.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendEquation.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; - colorBlendEquation.dstColorBlendFactor = VK_BLEND_FACTOR_DST_COLOR; - colorBlendEquation.alphaBlendOp = VK_BLEND_OP_ADD; - colorBlendEquation.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - colorBlendEquation.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - } - - vkCmdSetColorBlendEquationEXT(drawCmdBuffers[i], 0, 1, &colorBlendEquation); - } - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - scene.bindBuffers(drawCmdBuffers[i]); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - scene.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - scene.loadFromFile(getAssetPath() + "models/treasure_smooth.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - // Instead of having to create a pipeline for each state combination, we only create one pipeline and toggle the new dynamic states during command buffer creation - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::array shaderStages; - - // All dynamic states we want to use need to be enabled at pipeline creation - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH, }; - if (hasDynamicState) { - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_CULL_MODE_EXT); - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_FRONT_FACE_EXT); - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT); - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT); - } - if (hasDynamicState2) { - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT); - } - if (hasDynamicState3) { - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT); - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT); - } - - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); - - // Create the graphics pipeline state objects - - shaderStages[0] = loadShader(getShadersPath() + "pipelines/phong.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pipelines/phong.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Create the vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - - // Dynamic states are set with vkCmd* calls in the command buffer, so we need to load the function pointers depending on extension supports - if (hasDynamicState) { - vkCmdSetCullModeEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetCullModeEXT")); - vkCmdSetFrontFaceEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetFrontFaceEXT")); - vkCmdSetDepthWriteEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetDepthWriteEnableEXT")); - vkCmdSetDepthTestEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetDepthTestEnableEXT")); - } - - if (hasDynamicState2) { - vkCmdSetRasterizerDiscardEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetRasterizerDiscardEnableEXT")); - } - - if (hasDynamicState3) { - vkCmdSetColorBlendEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetColorBlendEnableEXT")); - vkCmdSetColorBlendEquationEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetColorBlendEquationEXT")); - } - - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - bool rebuildCB = false; - if (overlay->header("Dynamic state")) { - if (hasDynamicState) { - rebuildCB = overlay->comboBox("Cull mode", &dynamicState.cullMode, { "none", "front", "back" }); - rebuildCB |= overlay->comboBox("Front face", &dynamicState.frontFace, { "Counter clockwise", "Clockwise" }); - rebuildCB |= overlay->checkBox("Depth test", &dynamicState.depthTest); - rebuildCB |= overlay->checkBox("Depth write", &dynamicState.depthWrite); - } else { - overlay->text("Extension or features not supported"); - } - } - if (overlay->header("Dynamic state 2")) { - if (hasDynamicState2) { - rebuildCB |= overlay->checkBox("Rasterizer discard", &dynamicState2.rasterizerDiscardEnable); - } - else { - overlay->text("Extension or features not supported"); - } - } - if (overlay->header("Dynamic state 3")) { - if (hasDynamicState3) { - rebuildCB |= overlay->checkBox("Color blend", &dynamicState3.colorBlendEnable); - rebuildCB |= overlay->colorPicker("Clear color", clearColor); - } - else { - overlay->text("Extension or features not supported"); - } - } - if (rebuildCB) { - buildCommandBuffers(); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/dynamicuniformbuffer/README.md b/examples/dynamicuniformbuffer/README.md deleted file mode 100644 index f70d39bd..00000000 --- a/examples/dynamicuniformbuffer/README.md +++ /dev/null @@ -1,162 +0,0 @@ -# Dynamic uniform buffers - - - -## Synopsis - -Use a single uniform buffer object as a dynamic uniform buffer to draw multiple objects with different matrices from one big uniform buffer object. - -## Requirements - -The max. number of dynamic uniform buffers supported by the device should be checked with the [maxDescriptorSetUniformBuffersDynamic](http://vulkan.gpuinfo.org/listreports.php?limit=maxDescriptorSetUniformBuffersDynamic) device limit if you need more than the 8 dynamic uniform buffers required by the Vulkan specification. - -## Description - -This example demonstrates the use of dynamic uniform buffers (```VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC```) for offsetting into one or more uniform block objects when binding the descriptor set using [vkCmdBindDescriptorSets](https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkCmdBindDescriptorSets.html]). - -Instead of having single uniform buffers for each descriptor, dynamic uniform buffers can be used to store data for multiple descriptors in one single uniform buffer. - -This minimizes the number of descriptor sets required and may help in optimizing memory writes by e.g. only doing partial updates to that memory. - -For this example we will store the model matrices for multiple objects in one dynamic uniform buffer object and offset into this for each object draw. - -## Points of interest - -### Shader binding - -The shader binding itself does not have to be changed compared to a static (single) uniform buffer, as the offset is done in the actual application code. - -```glsl -layout (binding = 1) uniform UboInstance { - mat4 model; -} uboInstance; -``` - -### Preparing the uniform buffer (and memory) - -***Note:*** When preparing the (host) memory to back up the dynamic uniform buffer object it's crucial to take the [minUniformBufferOffsetAlignment](http://vulkan.gpuinfo.org/listreports.php?limit=minUniformBufferOffsetAlignment) limit of the implementation into account. - -Due to the implementation dependent alignment (different from our actual data size) we can't just use a vector and work with pointers instead: - -```cpp -struct UboDataDynamic { - glm::mat4 *model = nullptr; -} uboDataDynamic; -``` -First step is to calculate the alignment required for the data we want to store compared to the min. uniform buffer offset alignment reported by the GPU: - -```cpp -void prepareUniformBuffers() -{ - // Calculate required alignment based on minimum device offset alignment - size_t minUboAlignment = vulkanDevice->properties.limits.minUniformBufferOffsetAlignment; - dynamicAlignment = sizeof(glm::mat4); - if (minUboAlignment > 0) { - dynamicAlignment = (dynamicAlignment + minUboAlignment - 1) & ~(minUboAlignment - 1); - } -``` - -The max. allowed alignment (as per spec) is 256 bytes which may be much higher than the data size we actually need for each entry (one 4x4 matrix = 64 bytes). - -Now that we know the actual alignment required we can create our host memory for the dynamic uniform buffer: - -```cpp - size_t bufferSize = OBJECT_INSTANCES * dynamicAlignment; - uboDataDynamic.model = (glm::mat4*)alignedAlloc(bufferSize, dynamicAlignment); -``` -*(The ```alignedAlloc``` function is a small wrapper doing aligned memory allocation depending on the OS/Compiler)* - -Creating the buffer is the same as creating any other uniform buffer object: - -```cpp -vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &uniformBuffers.dynamic, bufferSize); -``` - -*(Updates will be flushed manually, the ```VK_MEMORY_PROPERTY_HOST_COHERENT_BIT``` flag will isn't used)* - -### Setting up the descriptors - -This is the same as for regular uniform buffers but with descriptor type ```VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC``` instead. - -#### Descriptor pool - -The example uses one dynamic uniform buffer, so we need to request at least one such descriptor type from the descriptor pool: - -```cpp -void setupDescriptors() -{ - ... - std::vector poolSizes = { - ... - vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1), - ... - }; -``` - -#### Descriptor set layout - -The vertex shader interface defines the uniform with the model matrices (sampled from the dynamic buffer) at binding 1, so we need to setup a matching descriptor set layout: - -```cpp -void setupDescriptors() -{ - ... - std::vector setLayoutBindings = { - ... - vkTools::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_VERTEX_BIT, 1), - ... - }; -``` - -#### Descriptor set - -The example uses the same descriptor set based on the set layout above for all objects in the scene. As with the layout we bind the dynamic uniform buffer to binding point 1 using the descriptor set up while creating the buffer earlier on. - -```cpp -void setupDescriptors() -{ - ... - std::vector writeDescriptorSets = { - // Binding 1 : Instance matrix as dynamic uniform buffer - vkTools::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, &uniformBuffers.dynamic.descriptor), - }; -``` - -### Using the dynamic uniform buffer - -Now that everything is set up, it's time to render the objects using the different matrices stored in the dynamic uniform buffer. - -```cpp -for (uint32_t j = 0; j < OBJECT_INSTANCES; j++) -{ - // One dynamic offset per dynamic descriptor to offset into the ubo containing all model matrices - uint32_t dynamicOffset = j * static_cast(dynamicAlignment); - // Bind the descriptor set for rendering a mesh using the dynamic offset - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 1, &dynamicOffset); - - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); -} -``` -For each object to be drawn the offset into the dynamic uniform buffer object's memory is calculated using the dynamic alignment set before buffer creation. - -The dynamic offset is then passed at descriptor set binding time using the ```dynamicOffsetCount``` and ```pDynamicOffsets``` parameters of ```vkCmdBindDescriptorSets```. - -For each dynamic uniform buffer in the descriptor set currently bound one pointer to an ```uint32_t``` has to be passed in the order of the dynamic buffers' binding indices. - -The data starting at the given offset is then passed to the shader for which the dynamic binding applies upon drawing with ```vkCmdDrawIndexed```. - -### Updating the buffer - -While creating the buffer we did not specify the ```VK_MEMORY_PROPERTY_HOST_COHERENT_BIT``` flag. While this is possible, in a real-world application you would usually only update the parts of the dynamic buffer that actually changed (e.g. only objects that moved since the last frame) and do a manual flush of the updated buffer memory part for better performance. - -This would be done using e.g. [vkFlushMappedMemoryRanges](https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkFlushMappedMemoryRanges.html). - -```cpp -VkMappedMemoryRange memoryRange = vkTools::initializers::mappedMemoryRange(); -memoryRange.memory = uniformBuffers.dynamic.memory; -memoryRange.size = sizeof(uboDataDynamic); -vkFlushMappedMemoryRanges(device, 1, &memoryRange); -``` -*(The example always updates the whole dynamic buffer's range)* - diff --git a/examples/dynamicuniformbuffer/dynamicuniformbuffer.cpp b/examples/dynamicuniformbuffer/dynamicuniformbuffer.cpp deleted file mode 100644 index 893e0e22..00000000 --- a/examples/dynamicuniformbuffer/dynamicuniformbuffer.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* -* Vulkan Example - Dynamic uniform buffers -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -* -* Summary: -* Demonstrates the use of dynamic uniform buffers. -* -* Instead of using one uniform buffer per-object, this example allocates one big uniform buffer -* with respect to the alignment reported by the device via minUniformBufferOffsetAlignment that -* contains all matrices for the objects in the scene. -* -* The used descriptor type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC then allows to set a dynamic -* offset used to pass data from the single uniform buffer to the connected shader binding point. -*/ - -#include "vulkanexamplebase.h" - -#define OBJECT_INSTANCES 125 - -// Vertex layout for this example -struct Vertex { - float pos[3]; - float color[3]; -}; - -// Wrapper functions for aligned memory allocation -// There is currently no standard for this in C++ that works across all platforms and vendors, so we abstract this -void* alignedAlloc(size_t size, size_t alignment) -{ - void *data = nullptr; -#if defined(_MSC_VER) || defined(__MINGW32__) - data = _aligned_malloc(size, alignment); -#else - int res = posix_memalign(&data, alignment, size); - if (res != 0) - data = nullptr; -#endif - return data; -} - -void alignedFree(void* data) -{ -#if defined(_MSC_VER) || defined(__MINGW32__) - _aligned_free(data); -#else - free(data); -#endif -} - -class VulkanExample : public VulkanExampleBase -{ -public: - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount{ 0 }; - - struct { - vks::Buffer view; - vks::Buffer dynamic; - } uniformBuffers; - - struct { - glm::mat4 projection; - glm::mat4 view; - } uboVS; - - // Store random per-object rotations - glm::vec3 rotations[OBJECT_INSTANCES]; - glm::vec3 rotationSpeeds[OBJECT_INSTANCES]; - - // One big uniform buffer that contains all matrices - // Note that we need to manually allocate the data to cope for GPU-specific uniform buffer offset alignments - struct UboDataDynamic { - glm::mat4* model{ nullptr }; - } uboDataDynamic; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - float animationTimer{ 0.0f }; - - size_t dynamicAlignment{ 0 }; - - VulkanExample() : VulkanExampleBase() - { - title = "Dynamic uniform buffers"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -30.0f)); - camera.setRotation(glm::vec3(0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - if (uboDataDynamic.model) { - alignedFree(uboDataDynamic.model); - } - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vertexBuffer.destroy(); - indexBuffer.destroy(); - uniformBuffers.view.destroy(); - uniformBuffers.dynamic.destroy(); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &vertexBuffer.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); - - // Render multiple objects using different model matrices by dynamically offsetting into one uniform buffer - for (uint32_t j = 0; j < OBJECT_INSTANCES; j++) - { - // One dynamic offset per dynamic descriptor to offset into the ubo containing all model matrices - uint32_t dynamicOffset = j * static_cast(dynamicAlignment); - // Bind the descriptor set for rendering a mesh using the dynamic offset - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 1, &dynamicOffset); - - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void generateCube() - { - // Setup vertices indices for a colored cube - std::vector vertices = { - { { -1.0f, -1.0f, 1.0f },{ 1.0f, 0.0f, 0.0f } }, - { { 1.0f, -1.0f, 1.0f },{ 0.0f, 1.0f, 0.0f } }, - { { 1.0f, 1.0f, 1.0f },{ 0.0f, 0.0f, 1.0f } }, - { { -1.0f, 1.0f, 1.0f },{ 0.0f, 0.0f, 0.0f } }, - { { -1.0f, -1.0f, -1.0f },{ 1.0f, 0.0f, 0.0f } }, - { { 1.0f, -1.0f, -1.0f },{ 0.0f, 1.0f, 0.0f } }, - { { 1.0f, 1.0f, -1.0f },{ 0.0f, 0.0f, 1.0f } }, - { { -1.0f, 1.0f, -1.0f },{ 0.0f, 0.0f, 0.0f } }, - }; - - std::vector indices = { - 0,1,2, 2,3,0, 1,5,6, 6,2,1, 7,6,5, 5,4,7, 4,0,3, 3,7,4, 4,5,1, 1,0,4, 3,2,6, 6,7,3, - }; - - indexCount = static_cast(indices.size()); - - // Create buffers - // For the sake of simplicity we won't stage the vertex data to the gpu memory - // Vertex buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &vertexBuffer, - vertices.size() * sizeof(Vertex), - vertices.data())); - // Index buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &indexBuffer, - indices.size() * sizeof(uint32_t), - indices.data())); - } - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - // Dynamic uniform buffer - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1) - }; - - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Dynamic uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_VERTEX_BIT, 1) - }; - - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - std::vector writeDescriptorSets = { - // Binding 0 : Projection/View matrix as uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.view.descriptor), - // Binding 1 : Instance matrix as dynamic uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, &uniformBuffers.dynamic.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Vertex bindings and attributes - VkVertexInputBindingDescription vertexInputBinding = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX) - }; - std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)), // Location 0 : Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color)), // Location 1 : Color - }; - VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputStateCI.vertexBindingDescriptionCount = 1; - vertexInputStateCI.pVertexBindingDescriptions = &vertexInputBinding; - vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - shaderStages[0] = loadShader(getShadersPath() + "dynamicuniformbuffer/base.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "dynamicuniformbuffer/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &vertexInputStateCI; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Allocate data for the dynamic uniform buffer object - // We allocate this manually as the alignment of the offset differs between GPUs - - // Calculate required alignment based on minimum device offset alignment - size_t minUboAlignment = vulkanDevice->properties.limits.minUniformBufferOffsetAlignment; - dynamicAlignment = sizeof(glm::mat4); - if (minUboAlignment > 0) { - dynamicAlignment = (dynamicAlignment + minUboAlignment - 1) & ~(minUboAlignment - 1); - } - - size_t bufferSize = OBJECT_INSTANCES * dynamicAlignment; - - uboDataDynamic.model = (glm::mat4*)alignedAlloc(bufferSize, dynamicAlignment); - assert(uboDataDynamic.model); - - std::cout << "minUniformBufferOffsetAlignment = " << minUboAlignment << std::endl; - std::cout << "dynamicAlignment = " << dynamicAlignment << std::endl; - - // Vertex shader uniform buffer block - - // Static shared uniform buffer object with projection and view matrix - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.view, - sizeof(uboVS))); - - // Uniform buffer object with per-object matrices - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - &uniformBuffers.dynamic, - bufferSize)); - - // Override descriptor range to [base, base + dynamicAlignment] - uniformBuffers.dynamic.descriptor.range = dynamicAlignment; - - // Map persistent - VK_CHECK_RESULT(uniformBuffers.view.map()); - VK_CHECK_RESULT(uniformBuffers.dynamic.map()); - - // Prepare per-object matrices with offsets and random rotations - std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::normal_distribution rndDist(-1.0f, 1.0f); - for (uint32_t i = 0; i < OBJECT_INSTANCES; i++) { - rotations[i] = glm::vec3(rndDist(rndEngine), rndDist(rndEngine), rndDist(rndEngine)) * 2.0f * (float)M_PI; - rotationSpeeds[i] = glm::vec3(rndDist(rndEngine), rndDist(rndEngine), rndDist(rndEngine)); - } - - updateUniformBuffers(); - updateDynamicUniformBuffer(); - } - - void updateUniformBuffers() - { - // Fixed ubo with projection and view matrices - uboVS.projection = camera.matrices.perspective; - uboVS.view = camera.matrices.view; - - memcpy(uniformBuffers.view.mapped, &uboVS, sizeof(uboVS)); - } - - void updateDynamicUniformBuffer() - { - // Update at max. 60 fps - animationTimer += frameTimer; - if (animationTimer <= 1.0f / 60.0f) { - return; - } - - // Dynamic ubo with per-object model matrices indexed by offsets in the command buffer - uint32_t dim = static_cast(pow(OBJECT_INSTANCES, (1.0f / 3.0f))); - glm::vec3 offset(5.0f); - - for (uint32_t x = 0; x < dim; x++) - { - for (uint32_t y = 0; y < dim; y++) - { - for (uint32_t z = 0; z < dim; z++) - { - uint32_t index = x * dim * dim + y * dim + z; - - // Aligned offset - glm::mat4* modelMat = (glm::mat4*)(((uint64_t)uboDataDynamic.model + (index * dynamicAlignment))); - - // Update rotations - rotations[index] += animationTimer * rotationSpeeds[index]; - - // Update matrices - glm::vec3 pos = glm::vec3(-((dim * offset.x) / 2.0f) + offset.x / 2.0f + x * offset.x, -((dim * offset.y) / 2.0f) + offset.y / 2.0f + y * offset.y, -((dim * offset.z) / 2.0f) + offset.z / 2.0f + z * offset.z); - *modelMat = glm::translate(glm::mat4(1.0f), pos); - *modelMat = glm::rotate(*modelMat, rotations[index].x, glm::vec3(1.0f, 1.0f, 0.0f)); - *modelMat = glm::rotate(*modelMat, rotations[index].y, glm::vec3(0.0f, 1.0f, 0.0f)); - *modelMat = glm::rotate(*modelMat, rotations[index].z, glm::vec3(0.0f, 0.0f, 1.0f)); - } - } - } - - animationTimer = 0.0f; - - memcpy(uniformBuffers.dynamic.mapped, uboDataDynamic.model, uniformBuffers.dynamic.size); - // Flush to make changes visible to the host - VkMappedMemoryRange memoryRange = vks::initializers::mappedMemoryRange(); - memoryRange.memory = uniformBuffers.dynamic.memory; - memoryRange.size = uniformBuffers.dynamic.size; - vkFlushMappedMemoryRanges(device, 1, &memoryRange); - } - - void prepare() - { - VulkanExampleBase::prepare(); - generateCube(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - updateDynamicUniformBuffer(); - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/gears/gears.cpp b/examples/gears/gears.cpp deleted file mode 100644 index f1cd272e..00000000 --- a/examples/gears/gears.cpp +++ /dev/null @@ -1,525 +0,0 @@ -/* -* Vulkan Example - Drawing multiple animated gears (emulating the look of glxgears) -* -* All gears are using single index, vertex and uniform buffers to show the Vulkan best practices of keeping the no. of buffer/memory allocations to a mimimum -* We use index offsets and instance indices to offset into the buffers at draw time for each gear -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -const uint32_t numGears = 3; - -// Used for passing the definition of a gear during construction -struct GearDefinition { - float innerRadius; - float outerRadius; - float width; - int numTeeth; - float toothDepth; - glm::vec3 color; - glm::vec3 pos; - float rotSpeed; - float rotOffset; -}; - -/* - * Gear - * This class contains the properties of a single gear and a function to generate vertices and indices - */ -class Gear -{ -public: - // Definition for the vertex data used to render the gears - struct Vertex { - glm::vec3 position; - glm::vec3 normal; - glm::vec3 color; - }; - - glm::vec3 color; - glm::vec3 pos; - float rotSpeed{ 0.0f }; - float rotOffset{ 0.0f }; - // These are used at draw time to offset into the single buffers - uint32_t indexCount{ 0 }; - uint32_t indexStart{ 0 }; - - // Generates the indices and vertices for this gear - // They are added to the vertex and index buffers passed into the function - // This way we can put all gears into single vertex and index buffers instead of having to allocate single buffers for each gear (which would be bad practice) - void generate(GearDefinition& gearDefinition, std::vector& vertexBuffer, std::vector& indexBuffer) { - this->color = gearDefinition.color; - this->pos = gearDefinition.pos; - this->rotOffset = gearDefinition.rotOffset; - this->rotSpeed = gearDefinition.rotSpeed; - - int i; - float r0, r1, r2; - float ta, da; - float u1, v1, u2, v2, len; - float cos_ta, cos_ta_1da, cos_ta_2da, cos_ta_3da, cos_ta_4da; - float sin_ta, sin_ta_1da, sin_ta_2da, sin_ta_3da, sin_ta_4da; - int32_t ix0, ix1, ix2, ix3, ix4, ix5; - - // We need to know where this triangle's indices start within the single index buffer - indexStart = static_cast(indexBuffer.size()); - - r0 = gearDefinition.innerRadius; - r1 = gearDefinition.outerRadius - gearDefinition.toothDepth / 2.0f; - r2 = gearDefinition.outerRadius + gearDefinition.toothDepth / 2.0f; - da = static_cast (2.0 * M_PI / gearDefinition.numTeeth / 4.0); - - glm::vec3 normal; - - // Use lambda functions to simplify vertex and face creation - auto addFace = [&indexBuffer](int a, int b, int c) { - indexBuffer.push_back(a); - indexBuffer.push_back(b); - indexBuffer.push_back(c); - }; - - auto addVertex = [this, &vertexBuffer](float x, float y, float z, glm::vec3 normal) { - Vertex v{}; - v.position = { x, y, z }; - v.normal = normal; - v.color = this->color; - vertexBuffer.push_back(v); - return static_cast(vertexBuffer.size()) - 1; - }; - - for (i = 0; i < gearDefinition.numTeeth; i++) { - ta = i * static_cast (2.0 * M_PI / gearDefinition.numTeeth); - - cos_ta = cos(ta); - cos_ta_1da = cos(ta + da); - cos_ta_2da = cos(ta + 2.0f * da); - cos_ta_3da = cos(ta + 3.0f * da); - cos_ta_4da = cos(ta + 4.0f * da); - sin_ta = sin(ta); - sin_ta_1da = sin(ta + da); - sin_ta_2da = sin(ta + 2.0f * da); - sin_ta_3da = sin(ta + 3.0f * da); - sin_ta_4da = sin(ta + 4.0f * da); - - u1 = r2 * cos_ta_1da - r1 * cos_ta; - v1 = r2 * sin_ta_1da - r1 * sin_ta; - len = sqrt(u1 * u1 + v1 * v1); - u1 /= len; - v1 /= len; - u2 = r1 * cos_ta_3da - r2 * cos_ta_2da; - v2 = r1 * sin_ta_3da - r2 * sin_ta_2da; - - // Front face - normal = glm::vec3(0.0f, 0.0f, 1.0f); - ix0 = addVertex(r0 * cos_ta, r0 * sin_ta, gearDefinition.width * 0.5f, normal); - ix1 = addVertex(r1 * cos_ta, r1 * sin_ta, gearDefinition.width * 0.5f, normal); - ix2 = addVertex(r0 * cos_ta, r0 * sin_ta, gearDefinition.width * 0.5f, normal); - ix3 = addVertex(r1 * cos_ta_3da, r1 * sin_ta_3da, gearDefinition.width * 0.5f, normal); - ix4 = addVertex(r0 * cos_ta_4da, r0 * sin_ta_4da, gearDefinition.width * 0.5f, normal); - ix5 = addVertex(r1 * cos_ta_4da, r1 * sin_ta_4da, gearDefinition.width * 0.5f, normal); - addFace(ix0, ix1, ix2); - addFace(ix1, ix3, ix2); - addFace(ix2, ix3, ix4); - addFace(ix3, ix5, ix4); - - // Teeth front face - normal = glm::vec3(0.0f, 0.0f, 1.0f); - ix0 = addVertex(r1 * cos_ta, r1 * sin_ta, gearDefinition.width * 0.5f, normal); - ix1 = addVertex(r2 * cos_ta_1da, r2 * sin_ta_1da, gearDefinition.width * 0.5f, normal); - ix2 = addVertex(r1 * cos_ta_3da, r1 * sin_ta_3da, gearDefinition.width * 0.5f, normal); - ix3 = addVertex(r2 * cos_ta_2da, r2 * sin_ta_2da, gearDefinition.width * 0.5f, normal); - addFace(ix0, ix1, ix2); - addFace(ix1, ix3, ix2); - - // Back face - normal = glm::vec3(0.0f, 0.0f, -1.0f); - ix0 = addVertex(r1 * cos_ta, r1 * sin_ta, -gearDefinition.width * 0.5f, normal); - ix1 = addVertex(r0 * cos_ta, r0 * sin_ta, -gearDefinition.width * 0.5f, normal); - ix2 = addVertex(r1 * cos_ta_3da, r1 * sin_ta_3da, -gearDefinition.width * 0.5f, normal); - ix3 = addVertex(r0 * cos_ta, r0 * sin_ta, -gearDefinition.width * 0.5f, normal); - ix4 = addVertex(r1 * cos_ta_4da, r1 * sin_ta_4da, -gearDefinition.width * 0.5f, normal); - ix5 = addVertex(r0 * cos_ta_4da, r0 * sin_ta_4da, -gearDefinition.width * 0.5f, normal); - addFace(ix0, ix1, ix2); - addFace(ix1, ix3, ix2); - addFace(ix2, ix3, ix4); - addFace(ix3, ix5, ix4); - - // Teeth back face - normal = glm::vec3(0.0f, 0.0f, -1.0f); - ix0 = addVertex(r1 * cos_ta_3da, r1 * sin_ta_3da, -gearDefinition.width * 0.5f, normal); - ix1 = addVertex(r2 * cos_ta_2da, r2 * sin_ta_2da, -gearDefinition.width * 0.5f, normal); - ix2 = addVertex(r1 * cos_ta, r1 * sin_ta, -gearDefinition.width * 0.5f, normal); - ix3 = addVertex(r2 * cos_ta_1da, r2 * sin_ta_1da, -gearDefinition.width * 0.5f, normal); - addFace(ix0, ix1, ix2); - addFace(ix1, ix3, ix2); - - // Outard teeth faces - normal = glm::vec3(v1, -u1, 0.0f); - ix0 = addVertex(r1 * cos_ta, r1 * sin_ta, gearDefinition.width * 0.5f, normal); - ix1 = addVertex(r1 * cos_ta, r1 * sin_ta, -gearDefinition.width * 0.5f, normal); - ix2 = addVertex(r2 * cos_ta_1da, r2 * sin_ta_1da, gearDefinition.width * 0.5f, normal); - ix3 = addVertex(r2 * cos_ta_1da, r2 * sin_ta_1da, -gearDefinition.width * 0.5f, normal); - addFace(ix0, ix1, ix2); - addFace(ix1, ix3, ix2); - - normal = glm::vec3(cos_ta, sin_ta, 0.0f); - ix0 = addVertex(r2 * cos_ta_1da, r2 * sin_ta_1da, gearDefinition.width * 0.5f, normal); - ix1 = addVertex(r2 * cos_ta_1da, r2 * sin_ta_1da, -gearDefinition.width * 0.5f, normal); - ix2 = addVertex(r2 * cos_ta_2da, r2 * sin_ta_2da, gearDefinition.width * 0.5f, normal); - ix3 = addVertex(r2 * cos_ta_2da, r2 * sin_ta_2da, -gearDefinition.width * 0.5f, normal); - addFace(ix0, ix1, ix2); - addFace(ix1, ix3, ix2); - - normal = glm::vec3(v2, -u2, 0.0f); - ix0 = addVertex(r2 * cos_ta_2da, r2 * sin_ta_2da, gearDefinition.width * 0.5f, normal); - ix1 = addVertex(r2 * cos_ta_2da, r2 * sin_ta_2da, -gearDefinition.width * 0.5f, normal); - ix2 = addVertex(r1 * cos_ta_3da, r1 * sin_ta_3da, gearDefinition.width * 0.5f, normal); - ix3 = addVertex(r1 * cos_ta_3da, r1 * sin_ta_3da, -gearDefinition.width * 0.5f, normal); - addFace(ix0, ix1, ix2); - addFace(ix1, ix3, ix2); - - normal = glm::vec3(cos_ta, sin_ta, 0.0f); - ix0 = addVertex(r1 * cos_ta_3da, r1 * sin_ta_3da, gearDefinition.width * 0.5f, normal); - ix1 = addVertex(r1 * cos_ta_3da, r1 * sin_ta_3da, -gearDefinition.width * 0.5f, normal); - ix2 = addVertex(r1 * cos_ta_4da, r1 * sin_ta_4da, gearDefinition.width * 0.5f, normal); - ix3 = addVertex(r1 * cos_ta_4da, r1 * sin_ta_4da, -gearDefinition.width * 0.5f, normal); - addFace(ix0, ix1, ix2); - addFace(ix1, ix3, ix2); - - // Inside cylinder faces - ix0 = addVertex(r0 * cos_ta, r0 * sin_ta, -gearDefinition.width * 0.5f, glm::vec3(-cos_ta, -sin_ta, 0.0f)); - ix1 = addVertex(r0 * cos_ta, r0 * sin_ta, gearDefinition.width * 0.5f, glm::vec3(-cos_ta, -sin_ta, 0.0f)); - ix2 = addVertex(r0 * cos_ta_4da, r0 * sin_ta_4da, -gearDefinition.width * 0.5f, glm::vec3(-cos_ta_4da, -sin_ta_4da, 0.0f)); - ix3 = addVertex(r0 * cos_ta_4da, r0 * sin_ta_4da, gearDefinition.width * 0.5f, glm::vec3(-cos_ta_4da, -sin_ta_4da, 0.0f)); - addFace(ix0, ix1, ix2); - addFace(ix1, ix3, ix2); - } - - // We need to know how many indices this triangle has at draw time - indexCount = static_cast(indexBuffer.size()) - indexStart; - } -}; - -/* - * VulkanExample - */ -class VulkanExample : public VulkanExampleBase -{ -public: - std::vector gears{}; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - // Even though this sample renders multiple objects (gears), we only use single buffers - // This is a best practices and Vulkan applications should keep the number of memory allocations as small as possible - // Having as little buffers as possible also reduces the number of buffer binds - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - struct UniformData - { - glm::mat4 projection; - glm::mat4 view; - glm::vec4 lightPos; - // The model matrix is used to rotate a given gear, so we have one mat4 per gear - glm::mat4 model[numGears]; - } uniformData; - vks::Buffer uniformBuffer; - - VulkanExample() : VulkanExampleBase() - { - title = "Vulkan gears"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 2.5f, -16.0f)); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.001f, 256.0f); - timerSpeed *= 0.25f; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - indexBuffer.destroy(); - vertexBuffer.destroy(); - uniformBuffer.destroy(); - } - } - - void prepareGears() - { - // Set up three differntly shaped and colored gears - std::vector gearDefinitions(3); - - // Large red gear - gearDefinitions[0].innerRadius = 1.0f; - gearDefinitions[0].outerRadius = 4.0f; - gearDefinitions[0].width = 1.0f; - gearDefinitions[0].numTeeth = 20; - gearDefinitions[0].toothDepth = 0.7f; - gearDefinitions[0].color = { 1.0f, 0.0f, 0.0f }; - gearDefinitions[0].pos = { -3.0f, 0.0f, 0.0f }; - gearDefinitions[0].rotSpeed = 1.0f; - gearDefinitions[0].rotOffset = 0.0f; - - // Medium sized green gear - gearDefinitions[1].innerRadius = 0.5f; - gearDefinitions[1].outerRadius = 2.0f; - gearDefinitions[1].width = 2.0f; - gearDefinitions[1].numTeeth = 10; - gearDefinitions[1].toothDepth = 0.7f; - gearDefinitions[1].color = { 0.0f, 1.0f, 0.2f }; - gearDefinitions[1].pos = { 3.1f, 0.0f, 0.0f }; - gearDefinitions[1].rotSpeed = -2.0f; - gearDefinitions[1].rotOffset = -9.0f; - - // Small blue gear - gearDefinitions[2].innerRadius = 1.3f; - gearDefinitions[2].outerRadius = 2.0f; - gearDefinitions[2].width = 0.5f; - gearDefinitions[2].numTeeth = 10; - gearDefinitions[2].toothDepth = 0.7f; - gearDefinitions[2].color = { 0.0f, 0.0f, 1.0f }; - gearDefinitions[2].pos = { -3.1f, -6.2f, 0.0f }; - gearDefinitions[2].rotSpeed = -2.0f; - gearDefinitions[2].rotOffset = -30.0f; - - // We'll be using a single vertex and a single index buffer for all the gears, no matter their number - // This is a Vulkan best practice as it keeps the no. of memory/buffer allocations low - // Vulkan offers all the tools to easily index into those buffers at a later point (see the buildCommandBuffers function) - std::vector vertices{}; - std::vector indices{}; - - // Fills the vertex and index buffers for each of the gear - gears.resize(gearDefinitions.size()); - for (int32_t i = 0; i < gears.size(); i++) { - gears[i].generate(gearDefinitions[i], vertices, indices); - } - - // Create buffers and stage to device for performances - size_t vertexBufferSize = vertices.size() * sizeof(Gear::Vertex); - size_t indexBufferSize = indices.size() * sizeof(uint32_t); - - vks::Buffer vertexStaging, indexStaging; - - // Temorary Staging buffers from vertex and index data - vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &vertexStaging, vertexBufferSize, vertices.data()); - vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &indexStaging, indexBufferSize, indices.data()); - // Device local buffers to where our staging buffers will be copied to - vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &vertexBuffer, vertexBufferSize); - vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &indexBuffer, indexBufferSize); - - // Copy host (staging) to device - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = {}; - copyRegion.size = vertexBufferSize; - vkCmdCopyBuffer(copyCmd, vertexStaging.buffer, vertexBuffer.buffer, 1, ©Region); - copyRegion.size = indexBufferSize; - vkCmdCopyBuffer(copyCmd, indexStaging.buffer, indexBuffer.buffer, 1, ©Region); - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - vertexStaging.destroy(); - indexStaging.destroy(); - } - - void setupDescriptors() - { - // We use a single descriptor set for the uniform data that contains both global matrices as well as per-gear model matrices - - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, static_cast(gears.size())); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor); - vkUpdateDescriptorSets(vulkanDevice->logicalDevice, 1, &writeDescriptorSet, 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - // Solid rendering pipeline - // Load shaders - std::array shaderStages; - - shaderStages[0] = loadShader(getShadersPath() + "gears/gears.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "gears/gears.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - // Vertex bindings and attributes to match the vertex buffers storing the vertices for the gears - VkVertexInputBindingDescription vertexInputBinding = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Gear::Vertex), VK_VERTEX_INPUT_RATE_VERTEX) - }; - std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Gear::Vertex, position)), // Location 0 : Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Gear::Vertex, normal)), // Location 1 : Normal - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Gear::Vertex, color)), // Location 2 : Color - }; - VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputStateCI.vertexBindingDescriptionCount = 1; - vertexInputStateCI.pVertexBindingDescriptions = &vertexInputBinding; - vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &vertexInputStateCI; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - // Vertices, indices and uniform data for all gears are stored in single buffers, so we only need to bind one buffer of each type and then index/offset into that for each separate gear - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &vertexBuffer.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); - for (auto j = 0; j < numGears; j++) { - // We use the instance index (last argument) to pass the index of the triangle to the shader - // With this we can index into the model matrices array of the uniform buffer like this (see gears.vert): - // ubo.model[gl_InstanceIndex]; - vkCmdDrawIndexed(drawCmdBuffers[i], gears[j].indexCount, 1, gears[j].indexStart, 0, j); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void prepareUniformBuffers() - { - // Create the vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - float degree = timer * 360.0f; - - // Camera specific global matrices - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.lightPos = glm::vec4(0.0f, 0.0f, 2.5f, 1.0f); - - // Update the model matrix for each gear that contains it's position and rotation - for (auto i = 0; i < numGears; i++) { - Gear gear = gears[i]; - uniformData.model[i] = glm::mat4(1.0f); - uniformData.model[i] = glm::translate(uniformData.model[i], gear.pos); - uniformData.model[i] = glm::rotate(uniformData.model[i], glm::radians((gear.rotSpeed * degree) + gear.rotOffset), glm::vec3(0.0f, 0.0f, 1.0f)); - } - - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - prepareGears(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/geometryshader/geometryshader.cpp b/examples/geometryshader/geometryshader.cpp deleted file mode 100644 index 8174a8d8..00000000 --- a/examples/geometryshader/geometryshader.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* -* Vulkan Example - Geometry shader (vertex normal debugging) -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool displayNormals = true; - - vkglTF::Model scene; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - } uniformData; - vks::Buffer uniformBuffer; - - struct { - VkPipeline solid{ VK_NULL_HANDLE }; - VkPipeline normals{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Geometry shader normal debugging"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -1.0f)); - camera.setRotation(glm::vec3(0.0f, -25.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 128.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.solid, nullptr); - vkDestroyPipeline(device, pipelines.normals, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Geometry shader support is required for this example - if (deviceFeatures.geometryShader) { - enabledFeatures.geometryShader = VK_TRUE; - } - else { - vks::tools::exitFatal("Selected GPU does not support geometry shaders!", VK_ERROR_FEATURE_NOT_PRESENT); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f - ); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdSetLineWidth(drawCmdBuffers[i], 1.0f); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - // Solid shading - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solid); - scene.draw(drawCmdBuffers[i]); - - // Normal debugging - if (displayNormals) - { - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.normals); - scene.draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - scene.loadFromFile(getAssetPath() + "models/suzanne.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Shader uniform ubo - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - //Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables, 0); - - // Tessellation pipeline - std::array shaderStages; - shaderStages[0] = loadShader(getShadersPath() + "geometryshader/base.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "geometryshader/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - shaderStages[2] = loadShader(getShadersPath() + "geometryshader/normaldebug.geom.spv", VK_SHADER_STAGE_GEOMETRY_BIT); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.renderPass = renderPass; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color }); - - // Normal debugging pipeline - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.normals)); - - // Solid rendering pipeline - shaderStages[0] = loadShader(getShadersPath() + "geometryshader/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "geometryshader/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - pipelineCI.stageCount = 2; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.solid)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - // Vertex shader - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->checkBox("Display normals", &displayNormals)) { - buildCommandBuffers(); - } - } - } - -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/gltfloading/gltfloading.cpp b/examples/gltfloading/gltfloading.cpp deleted file mode 100644 index 827f7dbb..00000000 --- a/examples/gltfloading/gltfloading.cpp +++ /dev/null @@ -1,744 +0,0 @@ -/* -* Vulkan Example - glTF scene loading and rendering -* -* Copyright (C) 2020-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -/* - * Shows how to load and display a simple scene from a glTF file - * Note that this isn't a complete glTF loader and only basic functions are shown here - * This means no complex materials, no animations, no skins, etc. - * For details on how glTF 2.0 works, see the official spec at https://github.com/KhronosGroup/glTF/tree/master/specification/2.0 - * - * Other samples will load models using a dedicated model loader with more features (see base/VulkanglTFModel.hpp) - * - * If you are looking for a complete glTF implementation, check out https://github.com/SaschaWillems/Vulkan-glTF-PBR/ - */ - -#define TINYGLTF_IMPLEMENTATION -#define STB_IMAGE_IMPLEMENTATION -#define TINYGLTF_NO_STB_IMAGE_WRITE -#ifdef VK_USE_PLATFORM_ANDROID_KHR -#define TINYGLTF_ANDROID_LOAD_FROM_ASSETS -#endif -#include "tiny_gltf.h" - -#include "vulkanexamplebase.h" - - -// Contains everything required to render a glTF model in Vulkan -// This class is heavily simplified (compared to glTF's feature set) but retains the basic glTF structure -class VulkanglTFModel -{ -public: - // The class requires some Vulkan objects so it can create it's own resources - vks::VulkanDevice* vulkanDevice; - VkQueue copyQueue; - - // The vertex layout for the samples' model - struct Vertex { - glm::vec3 pos; - glm::vec3 normal; - glm::vec2 uv; - glm::vec3 color; - }; - - // Single vertex buffer for all primitives - struct { - VkBuffer buffer; - VkDeviceMemory memory; - } vertices; - - // Single index buffer for all primitives - struct { - int count; - VkBuffer buffer; - VkDeviceMemory memory; - } indices; - - // The following structures roughly represent the glTF scene structure - // To keep things simple, they only contain those properties that are required for this sample - struct Node; - - // A primitive contains the data for a single draw call - struct Primitive { - uint32_t firstIndex; - uint32_t indexCount; - int32_t materialIndex; - }; - - // Contains the node's (optional) geometry and can be made up of an arbitrary number of primitives - struct Mesh { - std::vector primitives; - }; - - // A node represents an object in the glTF scene graph - struct Node { - Node* parent; - std::vector children; - Mesh mesh; - glm::mat4 matrix; - ~Node() { - for (auto& child : children) { - delete child; - } - } - }; - - // A glTF material stores information in e.g. the texture that is attached to it and colors - struct Material { - glm::vec4 baseColorFactor = glm::vec4(1.0f); - uint32_t baseColorTextureIndex; - }; - - // Contains the texture for a single glTF image - // Images may be reused by texture objects and are as such separated - struct Image { - vks::Texture2D texture; - // We also store (and create) a descriptor set that's used to access this texture from the fragment shader - VkDescriptorSet descriptorSet; - }; - - // A glTF texture stores a reference to the image and a sampler - // In this sample, we are only interested in the image - struct Texture { - int32_t imageIndex; - }; - - /* - Model data - */ - std::vector images; - std::vector textures; - std::vector materials; - std::vector nodes; - - ~VulkanglTFModel() - { - for (auto node : nodes) { - delete node; - } - // Release all Vulkan resources allocated for the model - vkDestroyBuffer(vulkanDevice->logicalDevice, vertices.buffer, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, vertices.memory, nullptr); - vkDestroyBuffer(vulkanDevice->logicalDevice, indices.buffer, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, indices.memory, nullptr); - for (Image image : images) { - vkDestroyImageView(vulkanDevice->logicalDevice, image.texture.view, nullptr); - vkDestroyImage(vulkanDevice->logicalDevice, image.texture.image, nullptr); - vkDestroySampler(vulkanDevice->logicalDevice, image.texture.sampler, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr); - } - } - - /* - glTF loading functions - - The following functions take a glTF input model loaded via tinyglTF and convert all required data into our own structure - */ - - void loadImages(tinygltf::Model& input) - { - // Images can be stored inside the glTF (which is the case for the sample model), so instead of directly - // loading them from disk, we fetch them from the glTF loader and upload the buffers - images.resize(input.images.size()); - for (size_t i = 0; i < input.images.size(); i++) { - tinygltf::Image& glTFImage = input.images[i]; - // Get the image data from the glTF loader - unsigned char* buffer = nullptr; - VkDeviceSize bufferSize = 0; - bool deleteBuffer = false; - // We convert RGB-only images to RGBA, as most devices don't support RGB-formats in Vulkan - if (glTFImage.component == 3) { - bufferSize = glTFImage.width * glTFImage.height * 4; - buffer = new unsigned char[bufferSize]; - unsigned char* rgba = buffer; - unsigned char* rgb = &glTFImage.image[0]; - for (size_t i = 0; i < glTFImage.width * glTFImage.height; ++i) { - memcpy(rgba, rgb, sizeof(unsigned char) * 3); - rgba += 4; - rgb += 3; - } - deleteBuffer = true; - } - else { - buffer = &glTFImage.image[0]; - bufferSize = glTFImage.image.size(); - } - // Load texture from image buffer - images[i].texture.fromBuffer(buffer, bufferSize, VK_FORMAT_R8G8B8A8_UNORM, glTFImage.width, glTFImage.height, vulkanDevice, copyQueue); - if (deleteBuffer) { - delete[] buffer; - } - } - } - - void loadTextures(tinygltf::Model& input) - { - textures.resize(input.textures.size()); - for (size_t i = 0; i < input.textures.size(); i++) { - textures[i].imageIndex = input.textures[i].source; - } - } - - void loadMaterials(tinygltf::Model& input) - { - materials.resize(input.materials.size()); - for (size_t i = 0; i < input.materials.size(); i++) { - // We only read the most basic properties required for our sample - tinygltf::Material glTFMaterial = input.materials[i]; - // Get the base color factor - if (glTFMaterial.values.find("baseColorFactor") != glTFMaterial.values.end()) { - materials[i].baseColorFactor = glm::make_vec4(glTFMaterial.values["baseColorFactor"].ColorFactor().data()); - } - // Get base color texture index - if (glTFMaterial.values.find("baseColorTexture") != glTFMaterial.values.end()) { - materials[i].baseColorTextureIndex = glTFMaterial.values["baseColorTexture"].TextureIndex(); - } - } - } - - void loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, std::vector& indexBuffer, std::vector& vertexBuffer) - { - VulkanglTFModel::Node* node = new VulkanglTFModel::Node{}; - node->matrix = glm::mat4(1.0f); - node->parent = parent; - - // Get the local node matrix - // It's either made up from translation, rotation, scale or a 4x4 matrix - if (inputNode.translation.size() == 3) { - node->matrix = glm::translate(node->matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); - } - if (inputNode.rotation.size() == 4) { - glm::quat q = glm::make_quat(inputNode.rotation.data()); - node->matrix *= glm::mat4(q); - } - if (inputNode.scale.size() == 3) { - node->matrix = glm::scale(node->matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); - } - if (inputNode.matrix.size() == 16) { - node->matrix = glm::make_mat4x4(inputNode.matrix.data()); - }; - - // Load node's children - if (inputNode.children.size() > 0) { - for (size_t i = 0; i < inputNode.children.size(); i++) { - loadNode(input.nodes[inputNode.children[i]], input , node, indexBuffer, vertexBuffer); - } - } - - // If the node contains mesh data, we load vertices and indices from the buffers - // In glTF this is done via accessors and buffer views - if (inputNode.mesh > -1) { - const tinygltf::Mesh mesh = input.meshes[inputNode.mesh]; - // Iterate through all primitives of this node's mesh - for (size_t i = 0; i < mesh.primitives.size(); i++) { - const tinygltf::Primitive& glTFPrimitive = mesh.primitives[i]; - uint32_t firstIndex = static_cast(indexBuffer.size()); - uint32_t vertexStart = static_cast(vertexBuffer.size()); - uint32_t indexCount = 0; - // Vertices - { - const float* positionBuffer = nullptr; - const float* normalsBuffer = nullptr; - const float* texCoordsBuffer = nullptr; - size_t vertexCount = 0; - - // Get buffer data for vertex positions - if (glTFPrimitive.attributes.find("POSITION") != glTFPrimitive.attributes.end()) { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("POSITION")->second]; - const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; - positionBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - vertexCount = accessor.count; - } - // Get buffer data for vertex normals - if (glTFPrimitive.attributes.find("NORMAL") != glTFPrimitive.attributes.end()) { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("NORMAL")->second]; - const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; - normalsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - } - // Get buffer data for vertex texture coordinates - // glTF supports multiple sets, we only load the first one - if (glTFPrimitive.attributes.find("TEXCOORD_0") != glTFPrimitive.attributes.end()) { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("TEXCOORD_0")->second]; - const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; - texCoordsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - } - - // Append data to model's vertex buffer - for (size_t v = 0; v < vertexCount; v++) { - Vertex vert{}; - vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f); - vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f))); - vert.uv = texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f); - vert.color = glm::vec3(1.0f); - vertexBuffer.push_back(vert); - } - } - // Indices - { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.indices]; - const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; - - indexCount += static_cast(accessor.count); - - // glTF supports different component types of indices - switch (accessor.componentType) { - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { - const uint32_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: { - const uint16_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: { - const uint8_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - default: - std::cerr << "Index component type " << accessor.componentType << " not supported!" << std::endl; - return; - } - } - Primitive primitive{}; - primitive.firstIndex = firstIndex; - primitive.indexCount = indexCount; - primitive.materialIndex = glTFPrimitive.material; - node->mesh.primitives.push_back(primitive); - } - } - - if (parent) { - parent->children.push_back(node); - } - else { - nodes.push_back(node); - } - } - - /* - glTF rendering functions - */ - - // Draw a single node including child nodes (if present) - void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node* node) - { - if (node->mesh.primitives.size() > 0) { - // Pass the node's matrix via push constants - // Traverse the node hierarchy to the top-most parent to get the final matrix of the current node - glm::mat4 nodeMatrix = node->matrix; - VulkanglTFModel::Node* currentParent = node->parent; - while (currentParent) { - nodeMatrix = currentParent->matrix * nodeMatrix; - currentParent = currentParent->parent; - } - // Pass the final matrix to the vertex shader using push constants - vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); - for (VulkanglTFModel::Primitive& primitive : node->mesh.primitives) { - if (primitive.indexCount > 0) { - // Get the texture index for this primitive - VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; - // Bind the descriptor for the current primitive's texture - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &images[texture.imageIndex].descriptorSet, 0, nullptr); - vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0); - } - } - } - for (auto& child : node->children) { - drawNode(commandBuffer, pipelineLayout, child); - } - } - - // Draw the glTF scene starting at the top-level-nodes - void draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout) - { - // All vertices and indices are stored in single buffers, so we only need to bind once - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertices.buffer, offsets); - vkCmdBindIndexBuffer(commandBuffer, indices.buffer, 0, VK_INDEX_TYPE_UINT32); - // Render all nodes at top-level - for (auto& node : nodes) { - drawNode(commandBuffer, pipelineLayout, node); - } - } - -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - bool wireframe = false; - - VulkanglTFModel glTFModel; - - struct ShaderData { - vks::Buffer buffer; - struct Values { - glm::mat4 projection; - glm::mat4 model; - glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, -5.0f, 1.0f); - glm::vec4 viewPos; - } values; - } shaderData; - - struct Pipelines { - VkPipeline solid{ VK_NULL_HANDLE }; - VkPipeline wireframe{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - struct DescriptorSetLayouts { - VkDescriptorSetLayout matrices{ VK_NULL_HANDLE }; - VkDescriptorSetLayout textures{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - VulkanExample() : VulkanExampleBase() - { - title = "glTF model rendering"; - camera.type = Camera::CameraType::lookat; - camera.flipY = true; - camera.setPosition(glm::vec3(0.0f, -0.1f, -1.0f)); - camera.setRotation(glm::vec3(0.0f, 45.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.solid, nullptr); - if (pipelines.wireframe != VK_NULL_HANDLE) { - vkDestroyPipeline(device, pipelines.wireframe, nullptr); - } - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr); - shaderData.buffer.destroy(); - } - } - - virtual void getEnabledFeatures() - { - // Fill mode non solid is required for wireframe display - if (deviceFeatures.fillModeNonSolid) { - enabledFeatures.fillModeNonSolid = VK_TRUE; - }; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - const VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - const VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - // Bind scene matrices descriptor to set 0 - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.solid); - glTFModel.draw(drawCmdBuffers[i], pipelineLayout); - drawUI(drawCmdBuffers[i]); - vkCmdEndRenderPass(drawCmdBuffers[i]); - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadglTFFile(std::string filename) - { - tinygltf::Model glTFInput; - tinygltf::TinyGLTF gltfContext; - std::string error, warning; - - this->device = device; - -#if defined(__ANDROID__) - // On Android all assets are packed with the apk in a compressed form, so we need to open them using the asset manager - // We let tinygltf handle this, by passing the asset manager of our app - tinygltf::asset_manager = androidApp->activity->assetManager; -#endif - bool fileLoaded = gltfContext.LoadASCIIFromFile(&glTFInput, &error, &warning, filename); - - // Pass some Vulkan resources required for setup and rendering to the glTF model loading class - glTFModel.vulkanDevice = vulkanDevice; - glTFModel.copyQueue = queue; - - std::vector indexBuffer; - std::vector vertexBuffer; - - if (fileLoaded) { - glTFModel.loadImages(glTFInput); - glTFModel.loadMaterials(glTFInput); - glTFModel.loadTextures(glTFInput); - const tinygltf::Scene& scene = glTFInput.scenes[0]; - for (size_t i = 0; i < scene.nodes.size(); i++) { - const tinygltf::Node node = glTFInput.nodes[scene.nodes[i]]; - glTFModel.loadNode(node, glTFInput, nullptr, indexBuffer, vertexBuffer); - } - } - else { - vks::tools::exitFatal("Could not open the glTF file.\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - return; - } - - // Create and upload vertex and index buffer - // We will be using one single vertex buffer and one single index buffer for the whole glTF scene - // Primitives (of the glTF model) will then index into these using index offsets - - size_t vertexBufferSize = vertexBuffer.size() * sizeof(VulkanglTFModel::Vertex); - size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t); - glTFModel.indices.count = static_cast(indexBuffer.size()); - - struct StagingBuffer { - VkBuffer buffer; - VkDeviceMemory memory; - } vertexStaging, indexStaging; - - // Create host visible staging buffers (source) - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - vertexBufferSize, - &vertexStaging.buffer, - &vertexStaging.memory, - vertexBuffer.data())); - // Index data - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - indexBufferSize, - &indexStaging.buffer, - &indexStaging.memory, - indexBuffer.data())); - - // Create device local buffers (target) - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - vertexBufferSize, - &glTFModel.vertices.buffer, - &glTFModel.vertices.memory)); - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - indexBufferSize, - &glTFModel.indices.buffer, - &glTFModel.indices.memory)); - - // Copy data from staging buffers (host) do device local buffer (gpu) - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = {}; - - copyRegion.size = vertexBufferSize; - vkCmdCopyBuffer( - copyCmd, - vertexStaging.buffer, - glTFModel.vertices.buffer, - 1, - ©Region); - - copyRegion.size = indexBufferSize; - vkCmdCopyBuffer( - copyCmd, - indexStaging.buffer, - glTFModel.indices.buffer, - 1, - ©Region); - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - // Free staging resources - vkDestroyBuffer(device, vertexStaging.buffer, nullptr); - vkFreeMemory(device, vertexStaging.memory, nullptr); - vkDestroyBuffer(device, indexStaging.buffer, nullptr); - vkFreeMemory(device, indexStaging.memory, nullptr); - } - - void loadAssets() - { - loadglTFFile(getAssetPath() + "models/FlightHelmet/glTF/FlightHelmet.gltf"); - } - - void setupDescriptors() - { - /* - This sample uses separate descriptor sets (and layouts) for the matrices and materials (textures) - */ - - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - // One combined image sampler per model image/texture - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(glTFModel.images.size())), - }; - // One set for matrices and one per model image/texture - const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + 1; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor set layout for passing matrices - VkDescriptorSetLayoutBinding setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&setLayoutBinding, 1); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices)); - // Descriptor set layout for passing material textures - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures)); - - // Descriptor set for scene matrices - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - // Descriptor sets for materials - for (auto& image : glTFModel.images) { - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &image.descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(image.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &image.texture.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - } - - void preparePipelines() - { - // Layout - // The pipeline layout uses both descriptor sets (set 0 = matrices, set 1 = material) - std::array setLayouts = { descriptorSetLayouts.matrices, descriptorSetLayouts.textures }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - // We will use push constants to push the local matrices of a primitive to the vertex shader - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); - // Push constant ranges are part of the pipeline layout - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentStateCI); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - // Vertex input bindings and attributes - const std::vector vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - }; - const std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)), // Location 0: Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)),// Location 1: Normal - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)), // Location 2: Texture coordinates - vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)), // Location 3: Color - }; - VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputStateCI.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - const std::array shaderStages = { - loadShader(getShadersPath() + "gltfloading/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "gltfloading/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pVertexInputState = &vertexInputStateCI; - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Solid rendering pipeline - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.solid)); - - // Wire frame rendering pipeline - if (deviceFeatures.fillModeNonSolid) { - rasterizationStateCI.polygonMode = VK_POLYGON_MODE_LINE; - rasterizationStateCI.lineWidth = 1.0f; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); - } - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &shaderData.buffer, sizeof(shaderData.values))); - // Map persistent - VK_CHECK_RESULT(shaderData.buffer.map()); - } - - void updateUniformBuffers() - { - shaderData.values.projection = camera.matrices.perspective; - shaderData.values.model = camera.matrices.view; - shaderData.values.viewPos = camera.viewPos; - memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - updateUniformBuffers(); - renderFrame(); - - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->checkBox("Wireframe", &wireframe)) { - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/gltfscenerendering/README.md b/examples/gltfscenerendering/README.md deleted file mode 100644 index 6c661e82..00000000 --- a/examples/gltfscenerendering/README.md +++ /dev/null @@ -1,323 +0,0 @@ -# glTF scene rendering - - - -## Synopsis - -Render a complete scene loaded from an glTF file. The sample is based on the [glTF scene](../gltfscene) sample, and adds data structures, functions and shaders required to render a more complex scene using Crytek's Sponza model. - -## Description - -This example demonstrates how to render a more complex scene loaded from a glTF model. - -It builds on the basic glTF scene sample but instead of using global pipelines, it adds per-material pipelines that are dynamically created from the material definitions of the glTF model. - -Those pipelines pass per-material parameters to the shader so different materials for e.g. displaying opaque and transparent objects can be built from a single shader. - -It also adds data structures, loading functions and shaders to do normal mapping and an easy way of toggling visibility for the scene nodes. - -Note that this is not a full glTF implementation as this would be beyond the scope of a simple example. For a complete glTF Vulkan implementation see [my Vulkan glTF PBR renderer](https://github.com/SaschaWillems/Vulkan-glTF-PBR/). - -For details on glTF refer to the [official glTF 2.0 specification](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0). - -## Points of interest - -**Note:** Points of interest are marked with a **POI** in the code comments: - -```cpp -// POI: This sample uses normal mapping, so we also need to load the tangents from the glTF file -``` - -For this sample, those points of interest mark additions and changes compared to the basic glTF sample. - -### Loading external images - -Unlike the other samples, the glTF scene used for this example doesn't embed the images but uses external ktx images instead. This makes loading a lot faster as the ktx image format natively maps to the GPU and no longer requires us to convert RGB to RGBA, but ktx also allows us to store the mip-chain in the image file itself. - -So instead of creating the textures from a buffer that has been converted from the embedded RGB images, we just load the ktx files from disk: - -```cpp -void VulkanglTFScene::loadImages(tinygltf::Model& input) -{ - images.resize(input.images.size()); - for (size_t i = 0; i < input.images.size(); i++) { - tinygltf::Image& glTFImage = input.images[i]; - images[i].texture.loadFromFile(path + "/" + glTFImage.uri, VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, copyQueue); - } -} -``` - -### Materials - -#### New Material properties - -```cpp -struct Material -{ - glm::vec4 baseColorFactor = glm::vec4(1.0f); - uint32_t baseColorTextureIndex; - uint32_t normalTextureIndex; - std::string alphaMode = "OPAQUE"; - float alphaCutOff; - bool doubleSided = false; - VkDescriptorSet descriptorSet; - VkPipeline pipeline; -}; -``` - -Several new properties have been added to the material class for this example that are taken from the glTF source. - -Along with the base color we now also get the index of the normal map for that material in ```normalTextureIndex```, and store several material properties required to render the different materials in this scene: - -- ```alphaMode```
-The alpha mode defines how the alpha value for this material is determined. For opaque materials it's ignored, for masked materials the shader will discard fragments based on the alpha cutoff. -- ```alphaCutOff```
-For masked materials, this value specifies the threshold between fully opaque and fully transparent. This is used to discard fragments in the fragment shader. -- ```doubleSided```
-This property is used to select the appropriate culling mode for this material. For double-sided materials, culling will be disabled. - -Retrieving these additional values is done here: - -```cpp -void VulkanglTFScene::loadMaterials(tinygltf::Model& input) -{ - materials.resize(input.materials.size()); - for (size_t i = 0; i < input.materials.size(); i++) { - tinygltf::Material glTFMaterial = input.materials[i]; - ... - materials[i].alphaMode = glTFMaterial.alphaMode; - materials[i].alphaCutOff = (float)glTFMaterial.alphaCutoff; - materials[i].doubleSided = glTFMaterial.doubleSided; - } -} -``` -**Note:** We only read the glTF material properties we use in this sample. There are many more, details on those can be found [here](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materials). - -#### Per-Material pipelines - -Unlike most of the other samples that use a few pre-defined pipelines, this sample will dynamically generate per-material pipelines based on material properties in the ```VulkanExample::preparePipelines()``` function - -We first setup pipeline state that's common for all materials: - -```cpp -// Setup common pipeline state properties... -VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = ... -VkPipelineRasterizationStateCreateInfo rasterizationStateCI = ... -VkPipelineColorBlendAttachmentState blendAttachmentStateCI = ... -... - -for (auto &material : glTFScene.materials) -{ - ... -``` - -For each material we then set constant properties for the fragment shader using specialization constants: - -```cpp - struct MaterialSpecializationData { - VkBool32 alphaMask; - float alphaMaskCutoff; - } materialSpecializationData; - - materialSpecializationData.alphaMask = material.alphaMode == "MASK"; - materialSpecializationData.alphaMaskCutoff = material.alphaCutOff; - - std::vector specializationMapEntries = { - vks::initializers::specializationMapEntry(0, offsetof(MaterialSpecializationData, alphaMask), sizeof(MaterialSpecializationData::alphaMask)), - vks::initializers::specializationMapEntry(1, offsetof(MaterialSpecializationData, alphaMaskCutoff), sizeof(MaterialSpecializationData::alphaMaskCutoff)), - }; - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(specializationMapEntries, sizeof(materialSpecializationData), &materialSpecializationData); - shaderStages[1].pSpecializationInfo = &specializationInfo; - ... -``` - -We also set the culling mode depending on whether this material is double-sided: - -```cpp - // For double sided materials, culling will be disabled - rasterizationStateCI.cullMode = material.doubleSided ? VK_CULL_MODE_NONE : VK_CULL_MODE_BACK_BIT; -``` - -With those setup we create a pipeline for the current material and store it as a property of the material class: - -```cpp - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &material.pipeline)); -} -``` - -The material now also get's it's own ```pipeline```. - -The alpha mask properties are used in the fragment shader to distinguish between opaque and transparent materials (```scene.frag```). - -Specialization constant declaration in the shaders's header: - -```glsl -layout (constant_id = 0) const bool ALPHA_MASK = false; -layout (constant_id = 1) const float ALPHA_MASK_CUTOFF = 0.0; -``` -*Note:* The default values provided in the shader are overwritten by the values passed at pipeline creation time. - -For alpha masked materials, fragments below the cutoff threshold are discarded: - -```glsl - vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0); - - if (ALPHA_MASK) { - if (color.a < ALPHA_MASK_CUTOFF) { - discard; - } - } -``` - -### Normal mapping - -This sample also adds tangent space normal mapping to the rendering equation to add additional detail to the scene, which requires loading additional data. - -#### Normal maps - -Along with the color maps, we now also load all normal maps. From the glTF POV those are just images like all other texture maps, and are stored in the image vector. So as for loading normal maps no code changes are required. The normal map images are then referenced by the index of the normal map of the material, which is now read in addition to the other material properties: - -```cpp -void VulkanglTFScene::loadMaterials(tinygltf::Model& input) -{ - materials.resize(input.materials.size()); - for (size_t i = 0; i < input.materials.size(); i++) { - tinygltf::Material glTFMaterial = input.materials[i]; - ... - // Get the normal map texture index - if (glTFMaterial.additionalValues.find("normalTexture") != glTFMaterial.additionalValues.end()) { - materials[i].normalTextureIndex = glTFMaterial.additionalValues["normalTexture"].TextureIndex(); - } - ... - } -} -``` -**Note:* Unlike the color map index, the normal map index is stored in the ```additionalValues``` of the material. - -The normal maps are then bound to binding 1 via the material's descriptor set in ```VulkanExample::setupDescriptors```: - -```cpp -for (auto& material : glTFScene.materials) { - ... - VkDescriptorImageInfo colorMap = glTFScene.getTextureDescriptor(material.baseColorTextureIndex); - VkDescriptorImageInfo normalMap = glTFScene.getTextureDescriptor(material.normalTextureIndex); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(material.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &colorMap), - vks::initializers::writeDescriptorSet(material.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &normalMap), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); -} -``` - -The descriptor set itself is then bound to set 1 at draw time in ```VulkanglTFScene::drawNode```: - -```cpp -if (node.mesh.primitives.size() > 0) { - ... - for (VulkanglTFScene::Primitive& primitive : node.mesh.primitives) { - if (primitive.indexCount > 0) { - VulkanglTFScene::Material& material = materials[primitive.materialIndex]; - ... - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &material.descriptorSet, 0, nullptr); - ... - } - } -} -``` - -Fragment shader interface in ```scene.frag```: - -```glsl -layout (set = 1, binding = 0) uniform sampler2D samplerColorMap; -layout (set = 1, binding = 1) uniform sampler2D samplerNormalMap; -``` - -#### Per-Vertex tangents - -Along with the normals we also need per-vertex tangents and bitangents for normal mapping. As the bitangent can easily be calculated using the normal and tangent, glTF only stores those two. - -So just like with other vertex data already loaded we need to check if there are tangents for a node and load them from the appropriate buffer using a glTF accessor: - -```cpp -void VulkanglTFScene::loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFScene::Node* parent, std::vector& indexBuffer, std::vector& vertexBuffer) -{ - VulkanglTFScene::Node node{}; - ... - - if (inputNode.mesh > -1) { - const tinygltf::Mesh mesh = input.meshes[inputNode.mesh]; - for (size_t i = 0; i < mesh.primitives.size(); i++) { - const tinygltf::Primitive& glTFPrimitive = mesh.primitives[i]; - // Vertices - { - ... - const float* tangentsBuffer = nullptr; - - if (glTFPrimitive.attributes.find("TANGENT") != glTFPrimitive.attributes.end()) { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("TANGENT")->second]; - const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; - tangentsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - } - - for (size_t v = 0; v < vertexCount; v++) { - Vertex vert{}; - ... - vert.tangent = tangentsBuffer ? glm::make_vec4(&tangentsBuffer[v * 4]) : glm::vec4(0.0f); - vertexBuffer.push_back(vert); - } - } - ... -``` - -**Note:** The tangent is a four-component vector, with the w-component storing the handedness of the tangent basis. This will be used later on in the shader. - -#### Shaders - -Normal mapping is applied in the ```scene.frag``` fragment shader and boils down to calculating a new world-space normal from the already provided per-vertex normal and the per-fragment tangent space normals provided via the materials' normal map. - -With the per-vertex normal and tangent values passed to the fragment shader, we simply change the way the per-fragment normal is calculated: - -```glsl -vec3 normal = normalize(inNormal); -vec3 tangent = normalize(inTangent.xyz); -vec3 bitangent = cross(inNormal, inTangent.xyz) * inTangent.w; -mat3 TBN = mat3(tangent, bitangent, normal); -vec3 localNormal = texture(samplerNormalMap, inUV).xyz * 2.0 - 1.0; -normal = normalize(TBN * localNormal); -``` - -As noted earlier, glTF does not store bitangents, but we can easily calculate them using the cross product of the normal and tangent. We also multiply this with the tangent's w-component which stores the handedness of the tangent. This is important, as this may differ between nodes in a glTF file. - -After that we calculate the tangent to world-space transformation matrix that is then applied to the per-fragment normal read from the normal map. - -This is then our new normal that is used for the lighting calculations to follow. - -### Rendering the scene - -Just like in the basic glTF sample, the scene hierarchy is added to the command buffer in ```VulkanglTFModel::draw```. Since glTF has a hierarchical node structure this function recursively calls ```VulkanglTFModel::drawNode``` for rendering a give node with it's children. - -The only real change in this sample is binding the per-material pipeline for a node's mesh: - -```cpp -void VulkanglTFScene::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node node) -{ - if (!node.visible) { - return; - } - if (node.mesh.primitives.size() > 0) { - ... - vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); - for (VulkanglTFScene::Primitive& primitive : node.mesh.primitives) { - if (primitive.indexCount > 0) { - VulkanglTFScene::Material& material = materials[primitive.materialIndex]; - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &material.descriptorSet, 0, nullptr); - vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0); - } - } - } - for (auto& child : node.children) { - drawNode(commandBuffer, pipelineLayout, child); - } -} -``` \ No newline at end of file diff --git a/examples/gltfscenerendering/gltfscenerendering.cpp b/examples/gltfscenerendering/gltfscenerendering.cpp deleted file mode 100644 index 7faef44c..00000000 --- a/examples/gltfscenerendering/gltfscenerendering.cpp +++ /dev/null @@ -1,663 +0,0 @@ -/* -* Vulkan Example - Scene rendering -* -* Copyright (C) 2020-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -* -* Summary: -* Render a complete scene loaded from an glTF file. The sample is based on the glTF model loading sample, -* and adds data structures, functions and shaders required to render a more complex scene using Crytek's Sponza model. -* -* This sample comes with a tutorial, see the README.md in this folder -*/ - -#include "gltfscenerendering.h" - -/* - Vulkan glTF scene class -*/ - -VulkanglTFScene::~VulkanglTFScene() -{ - for (auto node : nodes) { - delete node; - } - // Release all Vulkan resources allocated for the model - vkDestroyBuffer(vulkanDevice->logicalDevice, vertices.buffer, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, vertices.memory, nullptr); - vkDestroyBuffer(vulkanDevice->logicalDevice, indices.buffer, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, indices.memory, nullptr); - for (Image image : images) { - vkDestroyImageView(vulkanDevice->logicalDevice, image.texture.view, nullptr); - vkDestroyImage(vulkanDevice->logicalDevice, image.texture.image, nullptr); - vkDestroySampler(vulkanDevice->logicalDevice, image.texture.sampler, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr); - } - for (Material material : materials) { - vkDestroyPipeline(vulkanDevice->logicalDevice, material.pipeline, nullptr); - } -} - -/* - glTF loading functions - - The following functions take a glTF input model loaded via tinyglTF and convert all required data into our own structure -*/ - -void VulkanglTFScene::loadImages(tinygltf::Model& input) -{ - // POI: The textures for the glTF file used in this sample are stored as external ktx files, so we can directly load them from disk without the need for conversion - images.resize(input.images.size()); - for (size_t i = 0; i < input.images.size(); i++) { - tinygltf::Image& glTFImage = input.images[i]; - images[i].texture.loadFromFile(path + "/" + glTFImage.uri, VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, copyQueue); - } -} - -void VulkanglTFScene::loadTextures(tinygltf::Model& input) -{ - textures.resize(input.textures.size()); - for (size_t i = 0; i < input.textures.size(); i++) { - textures[i].imageIndex = input.textures[i].source; - } -} - -void VulkanglTFScene::loadMaterials(tinygltf::Model& input) -{ - materials.resize(input.materials.size()); - for (size_t i = 0; i < input.materials.size(); i++) { - // We only read the most basic properties required for our sample - tinygltf::Material glTFMaterial = input.materials[i]; - // Get the base color factor - if (glTFMaterial.values.find("baseColorFactor") != glTFMaterial.values.end()) { - materials[i].baseColorFactor = glm::make_vec4(glTFMaterial.values["baseColorFactor"].ColorFactor().data()); - } - // Get base color texture index - if (glTFMaterial.values.find("baseColorTexture") != glTFMaterial.values.end()) { - materials[i].baseColorTextureIndex = glTFMaterial.values["baseColorTexture"].TextureIndex(); - } - // Get the normal map texture index - if (glTFMaterial.additionalValues.find("normalTexture") != glTFMaterial.additionalValues.end()) { - materials[i].normalTextureIndex = glTFMaterial.additionalValues["normalTexture"].TextureIndex(); - } - // Get some additional material parameters that are used in this sample - materials[i].alphaMode = glTFMaterial.alphaMode; - materials[i].alphaCutOff = (float)glTFMaterial.alphaCutoff; - materials[i].doubleSided = glTFMaterial.doubleSided; - } -} - -void VulkanglTFScene::loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFScene::Node* parent, std::vector& indexBuffer, std::vector& vertexBuffer) -{ - VulkanglTFScene::Node* node = new VulkanglTFScene::Node{}; - node->name = inputNode.name; - node->parent = parent; - - // Get the local node matrix - // It's either made up from translation, rotation, scale or a 4x4 matrix - node->matrix = glm::mat4(1.0f); - if (inputNode.translation.size() == 3) { - node->matrix = glm::translate(node->matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); - } - if (inputNode.rotation.size() == 4) { - glm::quat q = glm::make_quat(inputNode.rotation.data()); - node->matrix *= glm::mat4(q); - } - if (inputNode.scale.size() == 3) { - node->matrix = glm::scale(node->matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); - } - if (inputNode.matrix.size() == 16) { - node->matrix = glm::make_mat4x4(inputNode.matrix.data()); - }; - - // Load node's children - if (inputNode.children.size() > 0) { - for (size_t i = 0; i < inputNode.children.size(); i++) { - loadNode(input.nodes[inputNode.children[i]], input, node, indexBuffer, vertexBuffer); - } - } - - // If the node contains mesh data, we load vertices and indices from the buffers - // In glTF this is done via accessors and buffer views - if (inputNode.mesh > -1) { - const tinygltf::Mesh mesh = input.meshes[inputNode.mesh]; - // Iterate through all primitives of this node's mesh - for (size_t i = 0; i < mesh.primitives.size(); i++) { - const tinygltf::Primitive& glTFPrimitive = mesh.primitives[i]; - uint32_t firstIndex = static_cast(indexBuffer.size()); - uint32_t vertexStart = static_cast(vertexBuffer.size()); - uint32_t indexCount = 0; - // Vertices - { - const float* positionBuffer = nullptr; - const float* normalsBuffer = nullptr; - const float* texCoordsBuffer = nullptr; - const float* tangentsBuffer = nullptr; - size_t vertexCount = 0; - - // Get buffer data for vertex normals - if (glTFPrimitive.attributes.find("POSITION") != glTFPrimitive.attributes.end()) { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("POSITION")->second]; - const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; - positionBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - vertexCount = accessor.count; - } - // Get buffer data for vertex normals - if (glTFPrimitive.attributes.find("NORMAL") != glTFPrimitive.attributes.end()) { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("NORMAL")->second]; - const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; - normalsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - } - // Get buffer data for vertex texture coordinates - // glTF supports multiple sets, we only load the first one - if (glTFPrimitive.attributes.find("TEXCOORD_0") != glTFPrimitive.attributes.end()) { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("TEXCOORD_0")->second]; - const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; - texCoordsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - } - // POI: This sample uses normal mapping, so we also need to load the tangents from the glTF file - if (glTFPrimitive.attributes.find("TANGENT") != glTFPrimitive.attributes.end()) { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("TANGENT")->second]; - const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; - tangentsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - } - - // Append data to model's vertex buffer - for (size_t v = 0; v < vertexCount; v++) { - Vertex vert{}; - vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f); - vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f))); - vert.uv = texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f); - vert.color = glm::vec3(1.0f); - vert.tangent = tangentsBuffer ? glm::make_vec4(&tangentsBuffer[v * 4]) : glm::vec4(0.0f); - vertexBuffer.push_back(vert); - } - } - // Indices - { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.indices]; - const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; - - indexCount += static_cast(accessor.count); - - // glTF supports different component types of indices - switch (accessor.componentType) { - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { - const uint32_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: { - const uint16_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: { - const uint8_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - default: - std::cerr << "Index component type " << accessor.componentType << " not supported!" << std::endl; - return; - } - } - Primitive primitive{}; - primitive.firstIndex = firstIndex; - primitive.indexCount = indexCount; - primitive.materialIndex = glTFPrimitive.material; - node->mesh.primitives.push_back(primitive); - } - } - - if (parent) { - parent->children.push_back(node); - } - else { - nodes.push_back(node); - } -} - -VkDescriptorImageInfo VulkanglTFScene::getTextureDescriptor(const size_t index) -{ - return images[index].texture.descriptor; -} - -/* - glTF rendering functions -*/ - -// Draw a single node including child nodes (if present) -void VulkanglTFScene::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node* node) -{ - if (!node->visible) { - return; - } - if (node->mesh.primitives.size() > 0) { - // Pass the node's matrix via push constants - // Traverse the node hierarchy to the top-most parent to get the final matrix of the current node - glm::mat4 nodeMatrix = node->matrix; - VulkanglTFScene::Node* currentParent = node->parent; - while (currentParent) { - nodeMatrix = currentParent->matrix * nodeMatrix; - currentParent = currentParent->parent; - } - // Pass the final matrix to the vertex shader using push constants - vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); - for (VulkanglTFScene::Primitive& primitive : node->mesh.primitives) { - if (primitive.indexCount > 0) { - VulkanglTFScene::Material& material = materials[primitive.materialIndex]; - // POI: Bind the pipeline for the node's material - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &material.descriptorSet, 0, nullptr); - vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0); - } - } - } - for (auto& child : node->children) { - drawNode(commandBuffer, pipelineLayout, child); - } -} - -// Draw the glTF scene starting at the top-level-nodes -void VulkanglTFScene::draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout) -{ - // All vertices and indices are stored in single buffers, so we only need to bind once - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertices.buffer, offsets); - vkCmdBindIndexBuffer(commandBuffer, indices.buffer, 0, VK_INDEX_TYPE_UINT32); - // Render all nodes at top-level - for (auto& node : nodes) { - drawNode(commandBuffer, pipelineLayout, node); - } -} - -/* - Vulkan Example class -*/ - -VulkanExample::VulkanExample() : VulkanExampleBase() -{ - title = "glTF scene rendering"; - camera.type = Camera::CameraType::firstperson; - camera.flipY = true; - camera.setPosition(glm::vec3(0.0f, 1.0f, 0.0f)); - camera.setRotation(glm::vec3(0.0f, -90.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); -} - -VulkanExample::~VulkanExample() -{ - if (device) { - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr); - shaderData.buffer.destroy(); - } -} - -void VulkanExample::getEnabledFeatures() -{ - enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy; -} - -void VulkanExample::buildCommandBuffers() -{ - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - const VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - const VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - // Bind scene matrices descriptor to set 0 - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - // POI: Draw the glTF scene - glTFScene.draw(drawCmdBuffers[i], pipelineLayout); - - drawUI(drawCmdBuffers[i]); - vkCmdEndRenderPass(drawCmdBuffers[i]); - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } -} - -void VulkanExample::loadglTFFile(std::string filename) -{ - tinygltf::Model glTFInput; - tinygltf::TinyGLTF gltfContext; - std::string error, warning; - - this->device = device; - -#if defined(__ANDROID__) - // On Android all assets are packed with the apk in a compressed form, so we need to open them using the asset manager - // We let tinygltf handle this, by passing the asset manager of our app - tinygltf::asset_manager = androidApp->activity->assetManager; -#endif - bool fileLoaded = gltfContext.LoadASCIIFromFile(&glTFInput, &error, &warning, filename); - - // Pass some Vulkan resources required for setup and rendering to the glTF model loading class - glTFScene.vulkanDevice = vulkanDevice; - glTFScene.copyQueue = queue; - - size_t pos = filename.find_last_of('/'); - glTFScene.path = filename.substr(0, pos); - - std::vector indexBuffer; - std::vector vertexBuffer; - - if (fileLoaded) { - glTFScene.loadImages(glTFInput); - glTFScene.loadMaterials(glTFInput); - glTFScene.loadTextures(glTFInput); - const tinygltf::Scene& scene = glTFInput.scenes[0]; - for (size_t i = 0; i < scene.nodes.size(); i++) { - const tinygltf::Node node = glTFInput.nodes[scene.nodes[i]]; - glTFScene.loadNode(node, glTFInput, nullptr, indexBuffer, vertexBuffer); - } - } - else { - vks::tools::exitFatal("Could not open the glTF file.\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - return; - } - - // Create and upload vertex and index buffer - // We will be using one single vertex buffer and one single index buffer for the whole glTF scene - // Primitives (of the glTF model) will then index into these using index offsets - - size_t vertexBufferSize = vertexBuffer.size() * sizeof(VulkanglTFScene::Vertex); - size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t); - glTFScene.indices.count = static_cast(indexBuffer.size()); - - struct StagingBuffer { - VkBuffer buffer; - VkDeviceMemory memory; - } vertexStaging, indexStaging; - - // Create host visible staging buffers (source) - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - vertexBufferSize, - &vertexStaging.buffer, - &vertexStaging.memory, - vertexBuffer.data())); - // Index data - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - indexBufferSize, - &indexStaging.buffer, - &indexStaging.memory, - indexBuffer.data())); - - // Create device local buffers (target) - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - vertexBufferSize, - &glTFScene.vertices.buffer, - &glTFScene.vertices.memory)); - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - indexBufferSize, - &glTFScene.indices.buffer, - &glTFScene.indices.memory)); - - // Copy data from staging buffers (host) do device local buffer (gpu) - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = {}; - - copyRegion.size = vertexBufferSize; - vkCmdCopyBuffer( - copyCmd, - vertexStaging.buffer, - glTFScene.vertices.buffer, - 1, - ©Region); - - copyRegion.size = indexBufferSize; - vkCmdCopyBuffer( - copyCmd, - indexStaging.buffer, - glTFScene.indices.buffer, - 1, - ©Region); - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - // Free staging resources - vkDestroyBuffer(device, vertexStaging.buffer, nullptr); - vkFreeMemory(device, vertexStaging.memory, nullptr); - vkDestroyBuffer(device, indexStaging.buffer, nullptr); - vkFreeMemory(device, indexStaging.memory, nullptr); -} - -void VulkanExample::loadAssets() -{ - loadglTFFile(getAssetPath() + "models/sponza/sponza.gltf"); -} - -void VulkanExample::setupDescriptors() -{ - /* - This sample uses separate descriptor sets (and layouts) for the matrices and materials (textures) - */ - - // One ubo to pass dynamic data to the shader - // Two combined image samplers per material as each material uses color and normal maps - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(glTFScene.materials.size()) * 2), - }; - // One set for matrices and one per model image/texture - const uint32_t maxSetCount = static_cast(glTFScene.images.size()) + 1; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor set layout for passing matrices - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices)); - - // Descriptor set layout for passing material textures - setLayoutBindings = { - // Color map - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // Normal map - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - descriptorSetLayoutCI.pBindings = setLayoutBindings.data(); - descriptorSetLayoutCI.bindingCount = 2; - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures)); - - // Descriptor set for scene matrices - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - - // Descriptor sets for materials - for (auto& material : glTFScene.materials) { - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &material.descriptorSet)); - VkDescriptorImageInfo colorMap = glTFScene.getTextureDescriptor(material.baseColorTextureIndex); - VkDescriptorImageInfo normalMap = glTFScene.getTextureDescriptor(material.normalTextureIndex); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(material.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &colorMap), - vks::initializers::writeDescriptorSet(material.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &normalMap), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } -} - -void VulkanExample::preparePipelines() -{ - // Layout - // Pipeline layout uses both descriptor sets (set 0 = matrices, set 1 = material) - std::array setLayouts = { descriptorSetLayouts.matrices, descriptorSetLayouts.textures }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - // We will use push constants to push the local matrices of a primitive to the vertex shader - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); - // Push constant ranges are part of the pipeline layout - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentStateCI); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); - std::array shaderStages; - - const std::vector vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFScene::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - }; - const std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFScene::Vertex, pos)), - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFScene::Vertex, normal)), - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFScene::Vertex, uv)), - vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFScene::Vertex, color)), - vks::initializers::vertexInputAttributeDescription(0, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFScene::Vertex, tangent)), - }; - VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(vertexInputBindings, vertexInputAttributes); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pVertexInputState = &vertexInputStateCI; - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - shaderStages[0] = loadShader(getShadersPath() + "gltfscenerendering/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "gltfscenerendering/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - // POI: Instead if using a few fixed pipelines, we create one pipeline for each material using the properties of that material - for (auto &material : glTFScene.materials) { - - struct MaterialSpecializationData { - VkBool32 alphaMask; - float alphaMaskCutoff; - } materialSpecializationData; - - materialSpecializationData.alphaMask = material.alphaMode == "MASK"; - materialSpecializationData.alphaMaskCutoff = material.alphaCutOff; - - // POI: Constant fragment shader material parameters will be set using specialization constants - std::vector specializationMapEntries = { - vks::initializers::specializationMapEntry(0, offsetof(MaterialSpecializationData, alphaMask), sizeof(MaterialSpecializationData::alphaMask)), - vks::initializers::specializationMapEntry(1, offsetof(MaterialSpecializationData, alphaMaskCutoff), sizeof(MaterialSpecializationData::alphaMaskCutoff)), - }; - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(specializationMapEntries, sizeof(materialSpecializationData), &materialSpecializationData); - shaderStages[1].pSpecializationInfo = &specializationInfo; - - // For double sided materials, culling will be disabled - rasterizationStateCI.cullMode = material.doubleSided ? VK_CULL_MODE_NONE : VK_CULL_MODE_BACK_BIT; - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &material.pipeline)); - } -} - -void VulkanExample::prepareUniformBuffers() -{ - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &shaderData.buffer, sizeof(shaderData.values))); - VK_CHECK_RESULT(shaderData.buffer.map()); -} - -void VulkanExample::updateUniformBuffers() -{ - shaderData.values.projection = camera.matrices.perspective; - shaderData.values.view = camera.matrices.view; - shaderData.values.viewPos = camera.viewPos; - memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); -} - -void VulkanExample::prepare() -{ - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; -} - -void VulkanExample::render() -{ - updateUniformBuffers(); - renderFrame(); -} - -void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) -{ - if (overlay->header("Visibility")) { - - if (overlay->button("All")) { - std::for_each(glTFScene.nodes.begin(), glTFScene.nodes.end(), [](VulkanglTFScene::Node* node) { node->visible = true; }); - buildCommandBuffers(); - } - ImGui::SameLine(); - if (overlay->button("None")) { - std::for_each(glTFScene.nodes.begin(), glTFScene.nodes.end(), [](VulkanglTFScene::Node* node) { node->visible = false; }); - buildCommandBuffers(); - } - ImGui::NewLine(); - - // POI: Create a list of glTF nodes for visibility toggle - ImGui::BeginChild("#nodelist", ImVec2(200.0f * overlay->scale, 340.0f * overlay->scale), false); - for (auto& node : glTFScene.nodes) - { - if (overlay->checkBox(node->name.c_str(), &node->visible)) - { - buildCommandBuffers(); - } - } - ImGui::EndChild(); - } -} - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/gltfscenerendering/gltfscenerendering.h b/examples/gltfscenerendering/gltfscenerendering.h deleted file mode 100644 index 7e71bbfe..00000000 --- a/examples/gltfscenerendering/gltfscenerendering.h +++ /dev/null @@ -1,170 +0,0 @@ -/* -* Vulkan Example - Scene rendering -* -* Copyright (C) 2020-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -* -* Summary: -* Render a complete scene loaded from an glTF file. The sample is based on the glTF model loading sample, -* and adds data structures, functions and shaders required to render a more complex scene using Crytek's Sponza model. -* -* This sample comes with a tutorial, see the README.md in this folder -*/ - -#define TINYGLTF_IMPLEMENTATION -#define STB_IMAGE_IMPLEMENTATION -#define TINYGLTF_NO_STB_IMAGE_WRITE -#define TINYGLTF_NO_STB_IMAGE -#define TINYGLTF_NO_EXTERNAL_IMAGE -#ifdef VK_USE_PLATFORM_ANDROID_KHR -#define TINYGLTF_ANDROID_LOAD_FROM_ASSETS -#endif -#include "tiny_gltf.h" - -#include "vulkanexamplebase.h" - - - // Contains everything required to render a basic glTF scene in Vulkan - // This class is heavily simplified (compared to glTF's feature set) but retains the basic glTF structure -class VulkanglTFScene -{ -public: - // The class requires some Vulkan objects so it can create it's own resources - vks::VulkanDevice* vulkanDevice; - VkQueue copyQueue; - - // The vertex layout for the samples' model - struct Vertex { - glm::vec3 pos; - glm::vec3 normal; - glm::vec2 uv; - glm::vec3 color; - glm::vec4 tangent; - }; - - // Single vertex buffer for all primitives - struct { - VkBuffer buffer; - VkDeviceMemory memory; - } vertices; - - // Single index buffer for all primitives - struct { - int count; - VkBuffer buffer; - VkDeviceMemory memory; - } indices; - - // The following structures roughly represent the glTF scene structure - // To keep things simple, they only contain those properties that are required for this sample - struct Node; - - // A primitive contains the data for a single draw call - struct Primitive { - uint32_t firstIndex; - uint32_t indexCount; - int32_t materialIndex; - }; - - // Contains the node's (optional) geometry and can be made up of an arbitrary number of primitives - struct Mesh { - std::vector primitives; - }; - - // A node represents an object in the glTF scene graph - struct Node { - Node* parent; - std::vector children; - Mesh mesh; - glm::mat4 matrix; - std::string name; - bool visible = true; - ~Node() { - for (auto& child : children) { - delete child; - } - } - }; - - // A glTF material stores information in e.g. the texture that is attached to it and colors - struct Material { - glm::vec4 baseColorFactor = glm::vec4(1.0f); - uint32_t baseColorTextureIndex; - uint32_t normalTextureIndex; - std::string alphaMode = "OPAQUE"; - float alphaCutOff; - bool doubleSided = false; - VkDescriptorSet descriptorSet; - VkPipeline pipeline; - }; - - // Contains the texture for a single glTF image - // Images may be reused by texture objects and are as such separated - struct Image { - vks::Texture2D texture; - }; - - // A glTF texture stores a reference to the image and a sampler - // In this sample, we are only interested in the image - struct Texture { - int32_t imageIndex; - }; - - /* - Model data - */ - std::vector images; - std::vector textures; - std::vector materials; - std::vector nodes; - - std::string path; - - ~VulkanglTFScene(); - VkDescriptorImageInfo getTextureDescriptor(const size_t index); - void loadImages(tinygltf::Model& input); - void loadTextures(tinygltf::Model& input); - void loadMaterials(tinygltf::Model& input); - void loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFScene::Node* parent, std::vector& indexBuffer, std::vector& vertexBuffer); - void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node* node); - void draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout); -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - VulkanglTFScene glTFScene; - - struct ShaderData { - vks::Buffer buffer; - struct Values { - glm::mat4 projection; - glm::mat4 view; - glm::vec4 lightPos = glm::vec4(0.0f, 2.5f, 0.0f, 1.0f); - glm::vec4 viewPos; - } values; - } shaderData; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - struct DescriptorSetLayouts { - VkDescriptorSetLayout matrices{ VK_NULL_HANDLE }; - VkDescriptorSetLayout textures{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - VulkanExample(); - ~VulkanExample(); - virtual void getEnabledFeatures(); - void buildCommandBuffers(); - void loadglTFFile(std::string filename); - void loadAssets(); - void setupDescriptors(); - void preparePipelines(); - void prepareUniformBuffers(); - void updateUniformBuffers(); - void prepare(); - virtual void render(); - virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); -}; diff --git a/examples/gltfskinning/README.md b/examples/gltfskinning/README.md deleted file mode 100644 index 88e199b3..00000000 --- a/examples/gltfskinning/README.md +++ /dev/null @@ -1,550 +0,0 @@ -# glTF vertex skinning - - - -## Synopsis - -Renders an animated glTF model with vertex skinning. The sample is based on the [glTF scene](../gltfscene) sample, and adds data structures, functions and shaders required to apply vertex skinning to a mesh. - -## Description - -This example demonstrates how to load and use the data structures required for animating a mesh with vertex skinning. - -Vertex skinning is a technique that uses per-vertex weights based on the current pose of a skeleton made up of bones. - -Animations then are applied to those bones instead and during rendering the matrices of those bones along with the vertex weights are used to calculate the final vertex positions. - -A good glTF skinning tutorial can be found [here](https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_020_Skins.md), so this readme only gives a coarse overview on the actual implementation instead of going into full detail on how vertex skinning works. - -Note that this is not a full glTF implementation as this would be beyond the scope of a simple example. For a complete glTF Vulkan implementation see https://github.com/SaschaWillems/Vulkan-glTF-PBR/. - -## Points of interest - -**Note:** Points of interest are marked with a **POI** in the code comments: - -```cpp -// POI: Get buffer data required for vertex skinning -``` - -### Data structures - -Several new data structures are required for doing animations with vertex skinning. The [official glTF spec](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skinned-mesh-attributes) has the details on those. - -#### Node additions - -```cpp -struct Node -{ - Node * parent; - uint32_t index; - std::vector children; - Mesh mesh; - glm::vec3 translation{}; - glm::vec3 scale{1.0f}; - glm::quat rotation{}; - int32_t skin = -1; - glm::mat4 matrix; - glm::mat4 getLocalMatrix(); -}; -``` - -The node now also stores the matrix components (```translation```, ```rotation``` ,```scale```) as they can be independently influenced. - -The ```skin``` member is the index of the skin (see below) that is applied to this node. - -A new function called ```getLocalMatrix``` is introduced that calculates the local matrix from the initial one and the current components. - -#### Vertex additions - -```cpp - struct Vertex - { - ... - glm::vec4 jointIndices; - glm::vec4 jointWeights; - }; -``` - -To calculate the final matrix to be applied to the vertex we now pass the indices of the joints (see below) and the weights of those, which determines how strongly this vertex is influenced by the joint. glTF support at max. four indices and weights per joint, so we pass them as four-component vectors. - -#### Skin - -[glTF spec chapter on skins](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins) - -```cpp -struct Skin -{ - std::string name; - Node * skeletonRoot = nullptr; - std::vector inverseBindMatrices; - std::vector joints; - vks::Buffer ssbo; - VkDescriptorSet descriptorSet; -}; -``` - -This struct stores all information required for applying a skin to a mesh. Most important are the ```inverseBindMatrices``` used to transform the geometry into the space of the accompanying joint node. The ```joints``` vector contains the nodes used as joints in this skin. - -We will pass the actual joint matrices for the current animation frame using a shader storage buffer object, so each skin also get's it's own ```ssboo``` along with a descriptor set to be bound at render time. - -#### Animations - -[glTF spec chapter on animations](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations) - -##### Animation sampler -```cpp -struct AnimationSampler -{ - std::string interpolation; - std::vector inputs; - std::vector outputsVec4; -}; -``` - -The animation sampler contains the key frame data read from a buffer using an accessor and the way the key frame is interpolated. This can be ```LINEAR```, which is just a simple linear interpolation over time, ```STEP```, which remains constant until the next key frame is reached, and ```CUBICSPLINE``` which uses a cubic spline with tangents for calculating the interpolated key frames. This is a bit more complex and separately documented in this [glTF spec chapter](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#appendix-c-spline-interpolation). - -**Note:** For simplicity, this sample only implements ```LINEAR``` interpolation. - -##### Animation channel - -```cpp -struct AnimationChannel -{ - std::string path; - Node * node; - uint32_t samplerIndex; -}; -``` - -The animation channel connects the node with a key frame specified by an animation sampler with the ```path``` member specifying the node property to animate, which is either ```translation```, ```rotation```, ```scale``` or ```weights```. The latter one refers to morph targets and not vertex weights (for skinning) and is not used in this sample. - -##### Animation -```cpp -struct Animation -{ - std::string name; - std::vector samplers; - std::vector channels; - float start = std::numeric_limits::max(); - float end = std::numeric_limits::min(); - float currentTime = 0.0f; -}; -``` - -The animation itself then contains the animation samplers and channels along with timing information. - -#### Loading and passing the data - -##### Vertex attributes - -This samples adds two new vertex attributes for passing per-vertex `joints` and `weights` information. As with other per-vertex attributes, these need to be loaded using glTF accessors in `VulkanglTFModel::loadNode`: - -```cpp -// Get vertex joint indices -if (glTFPrimitive.attributes.find("JOINTS_0") != glTFPrimitive.attributes.end()) -{ - const tinygltf::Accessor & accessor = input.accessors[glTFPrimitive.attributes.find("JOINTS_0")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - jointIndicesBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); -} -// Get vertex joint weights -if (glTFPrimitive.attributes.find("WEIGHTS_0") != glTFPrimitive.attributes.end()) -{ - const tinygltf::Accessor & accessor = input.accessors[glTFPrimitive.attributes.find("WEIGHTS_0")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - jointWeightsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); -} -``` - -As usual we check if those attributes actually exist inside the glTF file, and if so we use the accessor and buffer view to get a pointer to the required vertex attributes. - -The new attributes are added to the vertex input state of our pipeline in `VulkanExample::preparePipelines` at locations 4 and 5: - -```cpp -const std::vector vertexInputAttributes = { - ... - {4, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointIndices)}, - {5, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointWeights)}, -}; -``` - -Vertex shader interface in `skinnedmodel.vert`: - -```glsl -layout (location = 4) in vec4 inJointIndices; -layout (location = 5) in vec4 inJointWeights; -``` - -##### Skins - -Loading skins is done in `VulkanglTFModel::loadSkin` and aside from getting the required data from the glTF sources into our own structures, this method also creates a buffer for uploading the inverse bind matrices: - -```cpp -void VulkanglTFModel::loadSkins(tinygltf::Model &input) -{ - skins.resize(input.skins.size()); - - for (size_t i = 0; i < input.skins.size(); i++) - { - tinygltf::Skin glTFSkin = input.skins[i]; - ... - if (glTFSkin.inverseBindMatrices > -1) - { - const tinygltf::Accessor & accessor = input.accessors[glTFSkin.inverseBindMatrices]; - const tinygltf::BufferView &bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer & buffer = input.buffers[bufferView.buffer]; - skins[i].inverseBindMatrices.resize(accessor.count); - memcpy(skins[i].inverseBindMatrices.data(), &buffer.data[accessor.byteOffset + bufferView.byteOffset], accessor.count * sizeof(glm::mat4)); - - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &skins[i].ssbo, - sizeof(glm::mat4) * skins[i].inverseBindMatrices.size(), - skins[i].inverseBindMatrices.data()); - ... - } - } -``` - -Vertex shader interface in `skinnedmodel.vert`: - -```glsl -layout(std430, set = 1, binding = 0) readonly buffer JointMatrices { - mat4 jointMatrices[]; -}; -``` - -As with e.g. vertex attributes we retrieve the inverse bind matrices from the glTF accessor and buffer view. These are used at a later point for generating the actual animation matrices. - -We then create a shader storage buffer object (for each skin) big enough to hold all animation matrices. See [Updating the animations](#UpdatingAnimation) for how these are calculated and updated. - -**Note**: For simplicity we create a host visible SSBO. This makes code easier to read. In a real-world application you'd use a device local SSBO instead. - -##### Animations - -Loading the animation data is done in ```VulkanglTFModel::loadAnimations``` and is also mostly about getting the required data from glTF into our own sources, including sampler and channel data. - -The most interesting part is getting the input and output pairs for the animation's samplers, which are loaded using glTF's accessors. - -We first load the **sampler's input values**, containing keyframe time values. These are also used to determine the start and end time of the animation: - -```cpp -void VulkanglTFModel::loadAnimations(tinygltf::Model &input) - ... - for (size_t i = 0; i < input.animations.size(); i++) - { - ... - for (size_t j = 0; j < glTFAnimation.samplers.size(); j++) - { - ... - { - const tinygltf::Accessor & accessor = input.accessors[glTFSampler.input]; - const tinygltf::BufferView &bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer & buffer = input.buffers[bufferView.buffer]; - const void * dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; - const float * buf = static_cast(dataPtr); - for (size_t index = 0; index < accessor.count; index++) - { - dstSampler.inputs.push_back(buf[index]); - } - // Adjust animation's start and end times - for (auto input : animations[i].samplers[j].inputs) - { - if (input < animations[i].start) - { - animations[i].start = input; - }; - if (input > animations[i].end) - { - animations[i].end = input; - } - } - } -``` - -Next up are the **sampler's output values** containing the keyframe output values for the input time values read above: - -```cpp -void VulkanglTFModel::loadAnimations(tinygltf::Model &input) - ... - for (size_t i = 0; i < input.animations.size(); i++) - { - ... - for (size_t j = 0; j < glTFAnimation.samplers.size(); j++) - { - ... - // Read sampler keyframe output translate/rotate/scale values - { - const tinygltf::Accessor & accessor = input.accessors[glTFSampler.output]; - const tinygltf::BufferView &bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer & buffer = input.buffers[bufferView.buffer]; - const void * dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; - switch (accessor.type) - { - case TINYGLTF_TYPE_VEC3: { - const glm::vec3 *buf = static_cast(dataPtr); - for (size_t index = 0; index < accessor.count; index++) - { - dstSampler.outputsVec4.push_back(glm::vec4(buf[index], 0.0f)); - } - break; - } - case TINYGLTF_TYPE_VEC4: { - const glm::vec4 *buf = static_cast(dataPtr); - for (size_t index = 0; index < accessor.count; index++) - { - dstSampler.outputsVec4.push_back(buf[index]); - } - break; - } - default: { - std::cout << "unknown type" << std::endl; - break; - } - } - } -``` - -As the comment notes these outputs apply to a certain animation target path, which is either a translation, rotation or scale. - -The path and node that the output keyframe values are applied to are part of the animation's channel: - -```cpp - ... - for (size_t i = 0; i < input.animations.size(); i++) - { - ... - for (size_t j = 0; j < glTFAnimation.channels.size(); j++) - { - tinygltf::AnimationChannel glTFChannel = glTFAnimation.channels[j]; - AnimationChannel & dstChannel = animations[i].channels[j]; - dstChannel.path = glTFChannel.target_path; - dstChannel.samplerIndex = glTFChannel.sampler; - dstChannel.node = nodeFromIndex(glTFChannel.target_node); - } -``` - -So if the animation's channel's path is set to ```translation```, the keyframe output values contain translation values that are applied to the channel's node depending on the current animation time. - - -#### Updating the animation - -With all required structures loaded, the next step is updating the actual animation data. This is done inside the ```VulkanglTFModel::updateAnimation``` function, where the data from the animation's samplers and channels is applied to the animation targets of the destination node. - -We first update the active animation's current timestamp and also check if we need to restart it: - -```cpp -Animation &animation = animations[activeAnimation]; -animation.currentTime += deltaTime; -if (animation.currentTime > animation.end) -{ - animation.currentTime -= animation.end; -} -``` - -Next we go through all the channels that are applied to this animation (translation, rotation, scale) and try to find the input keyframe values for the current timestamp: - -```cpp -for (auto &channel : animation.channels) -{ - AnimationSampler &sampler = animation.samplers[channel.samplerIndex]; - for (size_t i = 0; i < sampler.inputs.size() - 1; i++) - { - // Get the input keyframe values for the current time stamp - if ((animation.currentTime >= sampler.inputs[i]) && (animation.currentTime <= sampler.inputs[i + 1])) - { - // Calculate interpolation value based on timestamp, Update node, see next paragraph - } - } -} -``` - -Inside the above loop we then calculate the interpolation value based on the animation's current time and the sampler's input keyframes for the current and next frame: - -```cpp -float a = (animation.currentTime - sampler.inputs[i]) / (sampler.inputs[i + 1] - sampler.inputs[i]); -``` - -This interpolation value is then used to apply the keyframe output values to the appropriate channel: - -```cpp -if (channel.path == "translation") -{ - channel.node->translation = glm::mix(sampler.outputsVec4[i], sampler.outputsVec4[i + 1], a); -} -if (channel.path == "rotation") -{ - glm::quat q1; - q1.x = sampler.outputsVec4[i].x; - q1.y = sampler.outputsVec4[i].y; - q1.z = sampler.outputsVec4[i].z; - q1.w = sampler.outputsVec4[i].w; - - glm::quat q2; - q2.x = sampler.outputsVec4[i + 1].x; - q2.y = sampler.outputsVec4[i + 1].y; - q2.z = sampler.outputsVec4[i + 1].z; - q2.w = sampler.outputsVec4[i + 1].w; - - channel.node->rotation = glm::normalize(glm::slerp(q1, q2, a)); -} -if (channel.path == "scale") -{ - channel.node->scale = glm::mix(sampler.outputsVec4[i], sampler.outputsVec4[i + 1], a); -} -``` - -**Note:** As mentioned earlier, this sample only supports linear interpolation types. - -Translation and scale is a simple linear interpolation between the output keyframe values of the current and next frame. - -Rotations use quaternions and as such are interpolated using spherical linear interpolation. - -After the node's animation components have been updated, we update all node joints: - -```cpp -for (auto &node : nodes) -{ - updateJoints(node); -} -``` - -The ```updateJoints``` function will calculate the actual joint matrices and update the shader storage buffer object: - -```cpp -void VulkanglTFModel::updateJoints(VulkanglTFModel::Node *node) -{ - if (node->skin > -1) - { - // Update the joint matrices - glm::mat4 inverseTransform = glm::inverse(getNodeMatrix(node)); - Skin skin = skins[node->skin]; - size_t numJoints = (uint32_t) skin.joints.size(); - std::vector jointMatrices(numJoints); - for (size_t i = 0; i < numJoints; i++) - { - jointMatrices[i] = getNodeMatrix(skin.joints[i]) * skin.inverseBindMatrices[i]; - jointMatrices[i] = inverseTransform * jointMatrices[i]; - } - // Update ssbo - skin.ssbo.copyTo(jointMatrices.data(), jointMatrices.size() * sizeof(glm::mat4)); - } - - for (auto &child : node->children) - { - updateJoints(child); - } -} -``` - -Note the use of the ```getNodeMatrix``` function which will return the current matrix of a given node calculated from the node hierarchy and the node's current translate/rotate/scale values updated earlier. This is the actual matrix that's updated by the current animation state. - -After this we copy the new joint matrices to the shader storage buffer object of the current skin to make it available to the shader. - -#### Rendering the model - -With all the matrices calculated and made available to the shaders, we can now finally render our animated model using vertex skinning. - -Rendering the glTF model is done in ```VulkanglTFModel::draw``` which is called at command buffer creation. Since glTF has a hierarchical node structure this function recursively calls ```VulkanglTFModel::drawNode``` for rendering a give node with it's children: - -```cpp -void VulkanglTFModel::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node node) -{ - if (node.mesh.primitives.size() > 0) - { - // Pass the node's matrix via push constants - // Traverse the node hierarchy to the top-most parent to get the final matrix of the current node - glm::mat4 nodeMatrix = node.matrix; - VulkanglTFModel::Node *currentParent = node.parent; - while (currentParent) - { - nodeMatrix = currentParent->matrix * nodeMatrix; - currentParent = currentParent->parent; - } - // Pass the final matrix to the vertex shader using push constants - vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); - // Bind SSBO with skin data for this node to set 1 - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &skins[node.skin].descriptorSet, 0, nullptr); - for (VulkanglTFModel::Primitive &primitive : node.mesh.primitives) - { - if (primitive.indexCount > 0) - { - ... - vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0); - } - } - } - for (auto &child : node.children) - { - drawNode(commandBuffer, pipelineLayout, *child); - } -} -``` - -There are two points-of-interest in this code related to vertex skinning. - -First is passing the (fixed) model matrix via a push constant, which is not directly related to the animation itself but required later on on the shader: - -```cpp -glm::mat4 nodeMatrix = node.matrix; -VulkanglTFModel::Node *currentParent = node.parent; -while (currentParent) -{ - nodeMatrix = currentParent->matrix * nodeMatrix; - currentParent = currentParent->parent; -} -// Pass the final matrix to the vertex shader using push constants -vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); -``` - -As this matrix won't change in our case, we pass this is a push constant to the vertex shader. - -And we also bind the shader storage buffer object of the skin so the vertex shader get's access to the current joint matrices for the skin to be applied to that particular node: - -```cpp -vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &skins[node.skin].descriptorSet, 0, nullptr); -``` - -With the application side setup done, we can now take a look at the vertex shader that does the actual vertex skinning (```skinnedmodel.vert```). - -As mentioned earlier, the interface has been expanded with values and attributes related to vertex skinning: - -```glsl -#version 450 - -... -layout (location = 4) in vec4 inJointIndices; -layout (location = 5) in vec4 inJointWeights; - -... - -layout(push_constant) uniform PushConsts { - mat4 model; -} primitive; - -layout(std430, set = 1, binding = 0) readonly buffer JointMatrices { - mat4 jointMatrices[]; -}; -``` - -Those are then used to calculate the skin matrix that's applied to the vertex position: - -```glsl -void main() -{ - ... - - mat4 skinMat = - inJointWeights.x * jointMatrices[int(inJointIndices.x)] + - inJointWeights.y * jointMatrices[int(inJointIndices.y)] + - inJointWeights.z * jointMatrices[int(inJointIndices.z)] + - inJointWeights.w * jointMatrices[int(inJointIndices.w)]; - - gl_Position = uboScene.projection * uboScene.view * primitive.model * skinMat * vec4(inPos.xyz, 1.0); - - ... -} -``` - -The skin matrix is a linear combination of the joint matrices. The indices of the joint matrices to be applied are taken from the ```inJointIndices``` vertex attribute, with each component (xyzw) storing one index, and those matrices are then weighted by the ```inJointWeights``` vertex attribute to calculate the final skin matrix that is applied to this vertex. \ No newline at end of file diff --git a/examples/gltfskinning/gltfskinning.cpp b/examples/gltfskinning/gltfskinning.cpp deleted file mode 100644 index 6bade0c6..00000000 --- a/examples/gltfskinning/gltfskinning.cpp +++ /dev/null @@ -1,1006 +0,0 @@ -/* -* Vulkan Example - glTF skinned animation -* -* Copyright (C) 2020-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -/* - * Shows how to load and display an animated scene from a glTF file using vertex skinning - * See the accompanying README.md for a short tutorial on the data structures and functions required for vertex skinning - * - * For details on how glTF 2.0 works, see the official spec at https://github.com/KhronosGroup/glTF/tree/master/specification/2.0 - * - * If you are looking for a complete glTF implementation, check out https://github.com/SaschaWillems/Vulkan-glTF-PBR/ - */ - -#include "gltfskinning.h" - -/* - - glTF model class - - Contains everything required to render a skinned glTF model in Vulkan - This class is simplified compared to glTF's feature set but retains the basic glTF structure required for this sample - - */ - -/* - Get a node's local matrix from the current translation, rotation and scale values - These are calculated from the current animation an need to be calculated dynamically - */ -glm::mat4 VulkanglTFModel::Node::getLocalMatrix() -{ - return glm::translate(glm::mat4(1.0f), translation) * glm::mat4(rotation) * glm::scale(glm::mat4(1.0f), scale) * matrix; -} - -/* - Release all Vulkan resources acquired for the model -*/ -VulkanglTFModel::~VulkanglTFModel() -{ - vkDestroyBuffer(vulkanDevice->logicalDevice, vertices.buffer, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, vertices.memory, nullptr); - vkDestroyBuffer(vulkanDevice->logicalDevice, indices.buffer, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, indices.memory, nullptr); - for (Image image : images) - { - vkDestroyImageView(vulkanDevice->logicalDevice, image.texture.view, nullptr); - vkDestroyImage(vulkanDevice->logicalDevice, image.texture.image, nullptr); - vkDestroySampler(vulkanDevice->logicalDevice, image.texture.sampler, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr); - } - for (Skin skin : skins) - { - skin.ssbo.destroy(); - } -} - -/* - glTF loading functions - - The following functions take a glTF input model loaded via tinyglTF and converts all required data into our own structures -*/ - -void VulkanglTFModel::loadImages(tinygltf::Model &input) -{ - // Images can be stored inside the glTF (which is the case for the sample model), so instead of directly - // loading them from disk, we fetch them from the glTF loader and upload the buffers - images.resize(input.images.size()); - for (size_t i = 0; i < input.images.size(); i++) - { - tinygltf::Image &glTFImage = input.images[i]; - // Get the image data from the glTF loader - unsigned char *buffer = nullptr; - VkDeviceSize bufferSize = 0; - bool deleteBuffer = false; - // We convert RGB-only images to RGBA, as most devices don't support RGB-formats in Vulkan - if (glTFImage.component == 3) - { - bufferSize = glTFImage.width * glTFImage.height * 4; - buffer = new unsigned char[bufferSize]; - unsigned char *rgba = buffer; - unsigned char *rgb = &glTFImage.image[0]; - for (size_t i = 0; i < glTFImage.width * glTFImage.height; ++i) - { - memcpy(rgba, rgb, sizeof(unsigned char) * 3); - rgba += 4; - rgb += 3; - } - deleteBuffer = true; - } - else - { - buffer = &glTFImage.image[0]; - bufferSize = glTFImage.image.size(); - } - // Load texture from image buffer - images[i].texture.fromBuffer(buffer, bufferSize, VK_FORMAT_R8G8B8A8_UNORM, glTFImage.width, glTFImage.height, vulkanDevice, copyQueue); - if (deleteBuffer) - { - delete[] buffer; - } - } -} - -void VulkanglTFModel::loadTextures(tinygltf::Model &input) -{ - textures.resize(input.textures.size()); - for (size_t i = 0; i < input.textures.size(); i++) - { - textures[i].imageIndex = input.textures[i].source; - } -} - -void VulkanglTFModel::loadMaterials(tinygltf::Model &input) -{ - materials.resize(input.materials.size()); - for (size_t i = 0; i < input.materials.size(); i++) - { - // We only read the most basic properties required for our sample - tinygltf::Material glTFMaterial = input.materials[i]; - // Get the base color factor - if (glTFMaterial.values.find("baseColorFactor") != glTFMaterial.values.end()) - { - materials[i].baseColorFactor = glm::make_vec4(glTFMaterial.values["baseColorFactor"].ColorFactor().data()); - } - // Get base color texture index - if (glTFMaterial.values.find("baseColorTexture") != glTFMaterial.values.end()) - { - materials[i].baseColorTextureIndex = glTFMaterial.values["baseColorTexture"].TextureIndex(); - } - } -} - -// Helper functions for locating glTF nodes - -VulkanglTFModel::Node *VulkanglTFModel::findNode(Node *parent, uint32_t index) -{ - Node *nodeFound = nullptr; - if (parent->index == index) - { - return parent; - } - for (auto &child : parent->children) - { - nodeFound = findNode(child, index); - if (nodeFound) - { - break; - } - } - return nodeFound; -} - -VulkanglTFModel::Node *VulkanglTFModel::nodeFromIndex(uint32_t index) -{ - Node *nodeFound = nullptr; - for (auto &node : nodes) - { - nodeFound = findNode(node, index); - if (nodeFound) - { - break; - } - } - return nodeFound; -} - -// POI: Load the skins from the glTF model -void VulkanglTFModel::loadSkins(tinygltf::Model &input) -{ - skins.resize(input.skins.size()); - - for (size_t i = 0; i < input.skins.size(); i++) - { - tinygltf::Skin glTFSkin = input.skins[i]; - - skins[i].name = glTFSkin.name; - // Find the root node of the skeleton - skins[i].skeletonRoot = nodeFromIndex(glTFSkin.skeleton); - - // Find joint nodes - for (int jointIndex : glTFSkin.joints) - { - Node *node = nodeFromIndex(jointIndex); - if (node) - { - skins[i].joints.push_back(node); - } - } - - // Get the inverse bind matrices from the buffer associated to this skin - if (glTFSkin.inverseBindMatrices > -1) - { - const tinygltf::Accessor & accessor = input.accessors[glTFSkin.inverseBindMatrices]; - const tinygltf::BufferView &bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer & buffer = input.buffers[bufferView.buffer]; - skins[i].inverseBindMatrices.resize(accessor.count); - memcpy(skins[i].inverseBindMatrices.data(), &buffer.data[accessor.byteOffset + bufferView.byteOffset], accessor.count * sizeof(glm::mat4)); - - // Store inverse bind matrices for this skin in a shader storage buffer object - // To keep this sample simple, we create a host visible shader storage buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &skins[i].ssbo, - sizeof(glm::mat4) * skins[i].inverseBindMatrices.size(), - skins[i].inverseBindMatrices.data())); - VK_CHECK_RESULT(skins[i].ssbo.map()); - } - } -} - -// POI: Load the animations from the glTF model -void VulkanglTFModel::loadAnimations(tinygltf::Model &input) -{ - animations.resize(input.animations.size()); - - for (size_t i = 0; i < input.animations.size(); i++) - { - tinygltf::Animation glTFAnimation = input.animations[i]; - animations[i].name = glTFAnimation.name; - - // Samplers - animations[i].samplers.resize(glTFAnimation.samplers.size()); - for (size_t j = 0; j < glTFAnimation.samplers.size(); j++) - { - tinygltf::AnimationSampler glTFSampler = glTFAnimation.samplers[j]; - AnimationSampler & dstSampler = animations[i].samplers[j]; - dstSampler.interpolation = glTFSampler.interpolation; - - // Read sampler keyframe input time values - { - const tinygltf::Accessor & accessor = input.accessors[glTFSampler.input]; - const tinygltf::BufferView &bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer & buffer = input.buffers[bufferView.buffer]; - const void * dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; - const float * buf = static_cast(dataPtr); - for (size_t index = 0; index < accessor.count; index++) - { - dstSampler.inputs.push_back(buf[index]); - } - // Adjust animation's start and end times - for (auto input : animations[i].samplers[j].inputs) - { - if (input < animations[i].start) - { - animations[i].start = input; - }; - if (input > animations[i].end) - { - animations[i].end = input; - } - } - } - - // Read sampler keyframe output translate/rotate/scale values - { - const tinygltf::Accessor & accessor = input.accessors[glTFSampler.output]; - const tinygltf::BufferView &bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer & buffer = input.buffers[bufferView.buffer]; - const void * dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; - switch (accessor.type) - { - case TINYGLTF_TYPE_VEC3: { - const glm::vec3 *buf = static_cast(dataPtr); - for (size_t index = 0; index < accessor.count; index++) - { - dstSampler.outputsVec4.push_back(glm::vec4(buf[index], 0.0f)); - } - break; - } - case TINYGLTF_TYPE_VEC4: { - const glm::vec4 *buf = static_cast(dataPtr); - for (size_t index = 0; index < accessor.count; index++) - { - dstSampler.outputsVec4.push_back(buf[index]); - } - break; - } - default: { - std::cout << "unknown type" << std::endl; - break; - } - } - } - } - - // Channels - animations[i].channels.resize(glTFAnimation.channels.size()); - for (size_t j = 0; j < glTFAnimation.channels.size(); j++) - { - tinygltf::AnimationChannel glTFChannel = glTFAnimation.channels[j]; - AnimationChannel & dstChannel = animations[i].channels[j]; - dstChannel.path = glTFChannel.target_path; - dstChannel.samplerIndex = glTFChannel.sampler; - dstChannel.node = nodeFromIndex(glTFChannel.target_node); - } - } -} - -void VulkanglTFModel::loadNode(const tinygltf::Node &inputNode, const tinygltf::Model &input, VulkanglTFModel::Node *parent, uint32_t nodeIndex, std::vector &indexBuffer, std::vector &vertexBuffer) -{ - VulkanglTFModel::Node *node = new VulkanglTFModel::Node{}; - node->parent = parent; - node->matrix = glm::mat4(1.0f); - node->index = nodeIndex; - node->skin = inputNode.skin; - - // Get the local node matrix - // It's either made up from translation, rotation, scale or a 4x4 matrix - if (inputNode.translation.size() == 3) - { - node->translation = glm::make_vec3(inputNode.translation.data()); - } - if (inputNode.rotation.size() == 4) - { - glm::quat q = glm::make_quat(inputNode.rotation.data()); - node->rotation = glm::mat4(q); - } - if (inputNode.scale.size() == 3) - { - node->scale = glm::make_vec3(inputNode.scale.data()); - } - if (inputNode.matrix.size() == 16) - { - node->matrix = glm::make_mat4x4(inputNode.matrix.data()); - }; - - // Load node's children - if (inputNode.children.size() > 0) - { - for (size_t i = 0; i < inputNode.children.size(); i++) - { - loadNode(input.nodes[inputNode.children[i]], input, node, inputNode.children[i], indexBuffer, vertexBuffer); - } - } - - // If the node contains mesh data, we load vertices and indices from the buffers - // In glTF this is done via accessors and buffer views - if (inputNode.mesh > -1) - { - const tinygltf::Mesh mesh = input.meshes[inputNode.mesh]; - // Iterate through all primitives of this node's mesh - for (size_t i = 0; i < mesh.primitives.size(); i++) - { - const tinygltf::Primitive &glTFPrimitive = mesh.primitives[i]; - uint32_t firstIndex = static_cast(indexBuffer.size()); - uint32_t vertexStart = static_cast(vertexBuffer.size()); - uint32_t indexCount = 0; - bool hasSkin = false; - // Vertices - { - const float * positionBuffer = nullptr; - const float * normalsBuffer = nullptr; - const float * texCoordsBuffer = nullptr; - const uint16_t *jointIndicesBuffer = nullptr; - const float * jointWeightsBuffer = nullptr; - size_t vertexCount = 0; - - // Get buffer data for vertex normals - if (glTFPrimitive.attributes.find("POSITION") != glTFPrimitive.attributes.end()) - { - const tinygltf::Accessor & accessor = input.accessors[glTFPrimitive.attributes.find("POSITION")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - positionBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - vertexCount = accessor.count; - } - // Get buffer data for vertex normals - if (glTFPrimitive.attributes.find("NORMAL") != glTFPrimitive.attributes.end()) - { - const tinygltf::Accessor & accessor = input.accessors[glTFPrimitive.attributes.find("NORMAL")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - normalsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - } - // Get buffer data for vertex texture coordinates - // glTF supports multiple sets, we only load the first one - if (glTFPrimitive.attributes.find("TEXCOORD_0") != glTFPrimitive.attributes.end()) - { - const tinygltf::Accessor & accessor = input.accessors[glTFPrimitive.attributes.find("TEXCOORD_0")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - texCoordsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - } - - // POI: Get buffer data required for vertex skinning - // Get vertex joint indices - if (glTFPrimitive.attributes.find("JOINTS_0") != glTFPrimitive.attributes.end()) - { - const tinygltf::Accessor & accessor = input.accessors[glTFPrimitive.attributes.find("JOINTS_0")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - jointIndicesBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - } - // Get vertex joint weights - if (glTFPrimitive.attributes.find("WEIGHTS_0") != glTFPrimitive.attributes.end()) - { - const tinygltf::Accessor & accessor = input.accessors[glTFPrimitive.attributes.find("WEIGHTS_0")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - jointWeightsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - } - - hasSkin = (jointIndicesBuffer && jointWeightsBuffer); - - // Append data to model's vertex buffer - for (size_t v = 0; v < vertexCount; v++) - { - Vertex vert{}; - vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f); - vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f))); - vert.uv = texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f); - vert.color = glm::vec3(1.0f); - vert.jointIndices = hasSkin ? glm::vec4(glm::make_vec4(&jointIndicesBuffer[v * 4])) : glm::vec4(0.0f); - vert.jointWeights = hasSkin ? glm::make_vec4(&jointWeightsBuffer[v * 4]) : glm::vec4(0.0f); - vertexBuffer.push_back(vert); - } - } - // Indices - { - const tinygltf::Accessor & accessor = input.accessors[glTFPrimitive.indices]; - const tinygltf::BufferView &bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer & buffer = input.buffers[bufferView.buffer]; - - indexCount += static_cast(accessor.count); - - // glTF supports different component types of indices - switch (accessor.componentType) - { - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { - const uint32_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) - { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: { - const uint16_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) - { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: { - const uint8_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) - { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - default: - std::cerr << "Index component type " << accessor.componentType << " not supported!" << std::endl; - return; - } - } - Primitive primitive{}; - primitive.firstIndex = firstIndex; - primitive.indexCount = indexCount; - primitive.materialIndex = glTFPrimitive.material; - node->mesh.primitives.push_back(primitive); - } - } - - if (parent) - { - parent->children.push_back(node); - } - else - { - nodes.push_back(node); - } -} - -/* - glTF vertex skinning functions -*/ - -// POI: Traverse the node hierarchy to the top-most parent to get the local matrix of the given node -glm::mat4 VulkanglTFModel::getNodeMatrix(VulkanglTFModel::Node *node) -{ - glm::mat4 nodeMatrix = node->getLocalMatrix(); - VulkanglTFModel::Node *currentParent = node->parent; - while (currentParent) - { - nodeMatrix = currentParent->getLocalMatrix() * nodeMatrix; - currentParent = currentParent->parent; - } - return nodeMatrix; -} - -// POI: Update the joint matrices from the current animation frame and pass them to the GPU -void VulkanglTFModel::updateJoints(VulkanglTFModel::Node *node) -{ - if (node->skin > -1) - { - // Update the joint matrices - glm::mat4 inverseTransform = glm::inverse(getNodeMatrix(node)); - Skin skin = skins[node->skin]; - size_t numJoints = (uint32_t) skin.joints.size(); - std::vector jointMatrices(numJoints); - for (size_t i = 0; i < numJoints; i++) - { - jointMatrices[i] = getNodeMatrix(skin.joints[i]) * skin.inverseBindMatrices[i]; - jointMatrices[i] = inverseTransform * jointMatrices[i]; - } - // Update ssbo - skin.ssbo.copyTo(jointMatrices.data(), jointMatrices.size() * sizeof(glm::mat4)); - } - - for (auto &child : node->children) - { - updateJoints(child); - } -} - -// POI: Update the current animation -void VulkanglTFModel::updateAnimation(float deltaTime) -{ - if (activeAnimation > static_cast(animations.size()) - 1) - { - std::cout << "No animation with index " << activeAnimation << std::endl; - return; - } - Animation &animation = animations[activeAnimation]; - animation.currentTime += deltaTime; - if (animation.currentTime > animation.end) - { - animation.currentTime -= animation.end; - } - - for (auto &channel : animation.channels) - { - AnimationSampler &sampler = animation.samplers[channel.samplerIndex]; - for (size_t i = 0; i < sampler.inputs.size() - 1; i++) - { - if (sampler.interpolation != "LINEAR") - { - std::cout << "This sample only supports linear interpolations\n"; - continue; - } - - // Get the input keyframe values for the current time stamp - if ((animation.currentTime >= sampler.inputs[i]) && (animation.currentTime <= sampler.inputs[i + 1])) - { - float a = (animation.currentTime - sampler.inputs[i]) / (sampler.inputs[i + 1] - sampler.inputs[i]); - if (channel.path == "translation") - { - channel.node->translation = glm::mix(sampler.outputsVec4[i], sampler.outputsVec4[i + 1], a); - } - if (channel.path == "rotation") - { - glm::quat q1; - q1.x = sampler.outputsVec4[i].x; - q1.y = sampler.outputsVec4[i].y; - q1.z = sampler.outputsVec4[i].z; - q1.w = sampler.outputsVec4[i].w; - - glm::quat q2; - q2.x = sampler.outputsVec4[i + 1].x; - q2.y = sampler.outputsVec4[i + 1].y; - q2.z = sampler.outputsVec4[i + 1].z; - q2.w = sampler.outputsVec4[i + 1].w; - - channel.node->rotation = glm::normalize(glm::slerp(q1, q2, a)); - } - if (channel.path == "scale") - { - channel.node->scale = glm::mix(sampler.outputsVec4[i], sampler.outputsVec4[i + 1], a); - } - } - } - } - for (auto &node : nodes) - { - updateJoints(node); - } -} - -/* - glTF rendering functions -*/ - -// Draw a single node including child nodes (if present) -void VulkanglTFModel::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node node) -{ - if (node.mesh.primitives.size() > 0) - { - // Pass the node's matrix via push constants - // Traverse the node hierarchy to the top-most parent to get the final matrix of the current node - glm::mat4 nodeMatrix = node.matrix; - VulkanglTFModel::Node *currentParent = node.parent; - while (currentParent) - { - nodeMatrix = currentParent->matrix * nodeMatrix; - currentParent = currentParent->parent; - } - // Pass the final matrix to the vertex shader using push constants - vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); - // Bind SSBO with skin data for this node to set 1 - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &skins[node.skin].descriptorSet, 0, nullptr); - for (VulkanglTFModel::Primitive &primitive : node.mesh.primitives) - { - if (primitive.indexCount > 0) - { - // Get the texture index for this primitive - VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; - // Bind the descriptor for the current primitive's texture to set 2 - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 2, 1, &images[texture.imageIndex].descriptorSet, 0, nullptr); - vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0); - } - } - } - for (auto &child : node.children) - { - drawNode(commandBuffer, pipelineLayout, *child); - } -} - -// Draw the glTF scene starting at the top-level-nodes -void VulkanglTFModel::draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout) -{ - // All vertices and indices are stored in single buffers, so we only need to bind once - VkDeviceSize offsets[1] = {0}; - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertices.buffer, offsets); - vkCmdBindIndexBuffer(commandBuffer, indices.buffer, 0, VK_INDEX_TYPE_UINT32); - // Render all nodes at top-level - for (auto &node : nodes) - { - drawNode(commandBuffer, pipelineLayout, *node); - } -} - -/* - - Vulkan Example class - -*/ - -VulkanExample::VulkanExample() : VulkanExampleBase() -{ - title = "glTF vertex skinning"; - camera.type = Camera::CameraType::lookat; - camera.flipY = true; - camera.setPosition(glm::vec3(0.0f, 0.75f, -2.0f)); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setPerspective(60.0f, (float) width / (float) height, 0.1f, 256.0f); -} - -VulkanExample::~VulkanExample() -{ - vkDestroyPipeline(device, pipelines.solid, nullptr); - if (pipelines.wireframe != VK_NULL_HANDLE) - { - vkDestroyPipeline(device, pipelines.wireframe, nullptr); - } - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.jointMatrices, nullptr); - - shaderData.buffer.destroy(); -} - -void VulkanExample::getEnabledFeatures() -{ - // Fill mode non solid is required for wireframe display - if (deviceFeatures.fillModeNonSolid) - { - enabledFeatures.fillModeNonSolid = VK_TRUE; - }; -} - -void VulkanExample::buildCommandBuffers() -{ - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = {{0.25f, 0.25f, 0.25f, 1.0f}}; - ; - clearValues[1].depthStencil = {1.0f, 0}; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - const VkViewport viewport = vks::initializers::viewport((float) width, (float) height, 0.0f, 1.0f); - const VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - // Bind scene matrices descriptor to set 0 - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.solid); - glTFModel.draw(drawCmdBuffers[i], pipelineLayout); - drawUI(drawCmdBuffers[i]); - vkCmdEndRenderPass(drawCmdBuffers[i]); - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } -} - -void VulkanExample::loadglTFFile(std::string filename) -{ - tinygltf::Model glTFInput; - tinygltf::TinyGLTF gltfContext; - std::string error, warning; - - this->device = device; - -#if defined(__ANDROID__) - // On Android all assets are packed with the apk in a compressed form, so we need to open them using the asset manager - // We let tinygltf handle this, by passing the asset manager of our app - tinygltf::asset_manager = androidApp->activity->assetManager; -#endif - bool fileLoaded = gltfContext.LoadASCIIFromFile(&glTFInput, &error, &warning, filename); - - // Pass some Vulkan resources required for setup and rendering to the glTF model loading class - glTFModel.vulkanDevice = vulkanDevice; - glTFModel.copyQueue = queue; - - std::vector indexBuffer; - std::vector vertexBuffer; - - if (fileLoaded) - { - glTFModel.loadImages(glTFInput); - glTFModel.loadMaterials(glTFInput); - glTFModel.loadTextures(glTFInput); - const tinygltf::Scene &scene = glTFInput.scenes[0]; - for (size_t i = 0; i < scene.nodes.size(); i++) - { - const tinygltf::Node node = glTFInput.nodes[scene.nodes[i]]; - glTFModel.loadNode(node, glTFInput, nullptr, scene.nodes[i], indexBuffer, vertexBuffer); - } - glTFModel.loadSkins(glTFInput); - glTFModel.loadAnimations(glTFInput); - // Calculate initial pose - for (auto node : glTFModel.nodes) - { - glTFModel.updateJoints(node); - } - } - else - { - vks::tools::exitFatal("Could not open the glTF file.\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - return; - } - - // Create and upload vertex and index buffer - size_t vertexBufferSize = vertexBuffer.size() * sizeof(VulkanglTFModel::Vertex); - size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t); - glTFModel.indices.count = static_cast(indexBuffer.size()); - - struct StagingBuffer - { - VkBuffer buffer; - VkDeviceMemory memory; - } vertexStaging, indexStaging; - - // Create host visible staging buffers (source) - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - vertexBufferSize, - &vertexStaging.buffer, - &vertexStaging.memory, - vertexBuffer.data())); - // Index data - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - indexBufferSize, - &indexStaging.buffer, - &indexStaging.memory, - indexBuffer.data())); - - // Create device local buffers (target) - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - vertexBufferSize, - &glTFModel.vertices.buffer, - &glTFModel.vertices.memory)); - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - indexBufferSize, - &glTFModel.indices.buffer, - &glTFModel.indices.memory)); - - // Copy data from staging buffers (host) do device local buffer (gpu) - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = {}; - copyRegion.size = vertexBufferSize; - vkCmdCopyBuffer(copyCmd, vertexStaging.buffer, glTFModel.vertices.buffer, 1, ©Region); - copyRegion.size = indexBufferSize; - vkCmdCopyBuffer(copyCmd, indexStaging.buffer, glTFModel.indices.buffer, 1, ©Region); - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - // Free staging resources - vkDestroyBuffer(device, vertexStaging.buffer, nullptr); - vkFreeMemory(device, vertexStaging.memory, nullptr); - vkDestroyBuffer(device, indexStaging.buffer, nullptr); - vkFreeMemory(device, indexStaging.memory, nullptr); -} - -void VulkanExample::setupDescriptors() -{ - /* - This sample uses separate descriptor sets (and layouts) for the matrices and materials (textures) - */ - - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - // One combined image sampler per material image/texture - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(glTFModel.images.size())), - // One ssbo per skin - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, static_cast(glTFModel.skins.size())), - }; - // Number of descriptor sets = One for the scene ubo + one per image + one per skin - const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + static_cast(glTFModel.skins.size()) + 1; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor set layouts - VkDescriptorSetLayoutBinding setLayoutBinding{}; - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&setLayoutBinding, 1); - - // Descriptor set layout for passing matrices - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices)); - - // Descriptor set layout for passing material textures - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures)); - - // Descriptor set layout for passing skin joint matrices - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); - - // Descriptor set for scene matrices - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - - // Descriptor set for glTF model skin joint matrices - for (auto &skin : glTFModel.skins) - { - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.jointMatrices, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &skin.descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(skin.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &skin.ssbo.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - - // Descriptor sets for glTF model materials - for (auto &image : glTFModel.images) - { - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &image.descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(image.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &image.texture.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } -} - -void VulkanExample::preparePipelines() -{ - // Layout - // The pipeline layout uses three sets: - // Set 0 = Scene matrices (VS) - // Set 1 = Joint matrices (VS) - // Set 2 = Material texture (FS) - std::array setLayouts = { - descriptorSetLayouts.matrices, - descriptorSetLayouts.jointMatrices, - descriptorSetLayouts.textures }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - - // We will use push constants to push the local matrices of a primitive to the vertex shader - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); - // Push constant ranges are part of the pipeline layout - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentStateCI); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - const std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); - // Vertex input bindings and attributes - const std::vector vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - }; - const std::vector vertexInputAttributes = { - {0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)}, - {1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)}, - {2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)}, - {3, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)}, - // POI: Per-Vertex Joint indices and weights are passed to the vertex shader - {4, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointIndices)}, - {5, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointWeights)}, - }; - - VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputStateCI.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - const std::array shaderStages = { - loadShader(getShadersPath() + "gltfskinning/skinnedmodel.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "gltfskinning/skinnedmodel.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT)}; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pVertexInputState = &vertexInputStateCI; - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Solid rendering pipeline - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.solid)); - - // Wire frame rendering pipeline - if (deviceFeatures.fillModeNonSolid) - { - rasterizationStateCI.polygonMode = VK_POLYGON_MODE_LINE; - rasterizationStateCI.lineWidth = 1.0f; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); - } -} - -void VulkanExample::prepareUniformBuffers() -{ - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &shaderData.buffer, sizeof(shaderData.values))); - VK_CHECK_RESULT(shaderData.buffer.map()); - updateUniformBuffers(); -} - -void VulkanExample::updateUniformBuffers() -{ - shaderData.values.projection = camera.matrices.perspective; - shaderData.values.model = camera.matrices.view; - memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); -} - -void VulkanExample::loadAssets() -{ - loadglTFFile(getAssetPath() + "models/CesiumMan/glTF/CesiumMan.gltf"); -} - -void VulkanExample::prepare() -{ - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; -} - -void VulkanExample::render() -{ - updateUniformBuffers(); - // POI: Advance animation - if (!paused) { - glTFModel.updateAnimation(frameTimer); - } - renderFrame(); -} - -void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay *overlay) -{ - if (overlay->header("Settings")) - { - if (overlay->checkBox("Wireframe", &wireframe)) - { - buildCommandBuffers(); - } - } -} - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/gltfskinning/gltfskinning.h b/examples/gltfskinning/gltfskinning.h deleted file mode 100644 index 367394c6..00000000 --- a/examples/gltfskinning/gltfskinning.h +++ /dev/null @@ -1,235 +0,0 @@ -/* -* Vulkan Example - glTF skinned animation -* -* Copyright (C) 2020-2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -/* - * Shows how to load and display an animated scene from a glTF file using vertex skinning - * See the accompanying README.md for a short tutorial on the data structures and functions required for vertex skinning - * - * For details on how glTF 2.0 works, see the official spec at https://github.com/KhronosGroup/glTF/tree/master/specification/2.0 - * - * If you are looking for a complete glTF implementation, check out https://github.com/SaschaWillems/Vulkan-glTF-PBR/ - */ - -#include -#include -#include -#include -#include - -#define GLM_FORCE_RADIANS -#define GLM_FORCE_DEPTH_ZERO_TO_ONE -#include -#include -#include - -#define TINYGLTF_IMPLEMENTATION -#define STB_IMAGE_IMPLEMENTATION -#define TINYGLTF_NO_STB_IMAGE_WRITE -#ifdef VK_USE_PLATFORM_ANDROID_KHR -# define TINYGLTF_ANDROID_LOAD_FROM_ASSETS -#endif -#include "tiny_gltf.h" - -#include "vulkanexamplebase.h" -#include - - -// Contains everything required to render a glTF model in Vulkan -// This class is heavily simplified (compared to glTF's feature set) but retains the basic glTF structure -class VulkanglTFModel -{ - public: - vks::VulkanDevice *vulkanDevice; - VkQueue copyQueue; - - /* - Base glTF structures, see gltfscene sample for details - */ - - struct Vertices - { - VkBuffer buffer; - VkDeviceMemory memory; - } vertices; - - struct Indices - { - int count; - VkBuffer buffer; - VkDeviceMemory memory; - } indices; - - struct Node; - - struct Material - { - glm::vec4 baseColorFactor = glm::vec4(1.0f); - uint32_t baseColorTextureIndex; - }; - - struct Image - { - vks::Texture2D texture; - VkDescriptorSet descriptorSet; - }; - - struct Texture - { - int32_t imageIndex; - }; - - struct Primitive - { - uint32_t firstIndex; - uint32_t indexCount; - int32_t materialIndex; - }; - - struct Mesh - { - std::vector primitives; - }; - - struct Node - { - Node * parent; - uint32_t index; - std::vector children; - Mesh mesh; - glm::vec3 translation{}; - glm::vec3 scale{1.0f}; - glm::quat rotation{}; - int32_t skin = -1; - glm::mat4 matrix; - glm::mat4 getLocalMatrix(); - }; - - struct Vertex - { - glm::vec3 pos; - glm::vec3 normal; - glm::vec2 uv; - glm::vec3 color; - glm::vec4 jointIndices; - glm::vec4 jointWeights; - }; - - /* - Skin structure - */ - - struct Skin - { - std::string name; - Node * skeletonRoot = nullptr; - std::vector inverseBindMatrices; - std::vector joints; - vks::Buffer ssbo; - VkDescriptorSet descriptorSet; - }; - - /* - Animation related structures - */ - - struct AnimationSampler - { - std::string interpolation; - std::vector inputs; - std::vector outputsVec4; - }; - - struct AnimationChannel - { - std::string path; - Node * node; - uint32_t samplerIndex; - }; - - struct Animation - { - std::string name; - std::vector samplers; - std::vector channels; - float start = std::numeric_limits::max(); - float end = std::numeric_limits::min(); - float currentTime = 0.0f; - }; - - std::vector images; - std::vector textures; - std::vector materials; - std::vector nodes; - std::vector skins; - std::vector animations; - - uint32_t activeAnimation = 0; - - ~VulkanglTFModel(); - void loadImages(tinygltf::Model &input); - void loadTextures(tinygltf::Model &input); - void loadMaterials(tinygltf::Model &input); - Node * findNode(Node *parent, uint32_t index); - Node * nodeFromIndex(uint32_t index); - void loadSkins(tinygltf::Model &input); - void loadAnimations(tinygltf::Model &input); - void loadNode(const tinygltf::Node &inputNode, const tinygltf::Model &input, VulkanglTFModel::Node *parent, uint32_t nodeIndex, std::vector &indexBuffer, std::vector &vertexBuffer); - glm::mat4 getNodeMatrix(VulkanglTFModel::Node *node); - void updateJoints(VulkanglTFModel::Node *node); - void updateAnimation(float deltaTime); - void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node node); - void draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout); -}; - -class VulkanExample : public VulkanExampleBase -{ - public: - bool wireframe = false; - - struct ShaderData - { - vks::Buffer buffer; - struct Values - { - glm::mat4 projection; - glm::mat4 model; - glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, 5.0f, 1.0f); - } values; - } shaderData; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - struct Pipelines - { - VkPipeline solid{ VK_NULL_HANDLE }; - VkPipeline wireframe{ VK_NULL_HANDLE }; - } pipelines; - - struct DescriptorSetLayouts - { - VkDescriptorSetLayout matrices{ VK_NULL_HANDLE }; - VkDescriptorSetLayout textures{ VK_NULL_HANDLE }; - VkDescriptorSetLayout jointMatrices{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - VulkanglTFModel glTFModel; - - VulkanExample(); - ~VulkanExample(); - void loadglTFFile(std::string filename); - virtual void getEnabledFeatures(); - void buildCommandBuffers(); - void loadAssets(); - void setupDescriptors(); - void preparePipelines(); - void prepareUniformBuffers(); - void updateUniformBuffers(); - void prepare(); - virtual void render(); - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay); -}; diff --git a/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp b/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp deleted file mode 100644 index cc0d711a..00000000 --- a/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp +++ /dev/null @@ -1,528 +0,0 @@ -/* -* Vulkan Example - Using VK_EXT_graphics_pipeline_library -* -* Copyright (C) 2022-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" -#include -#include - -class VulkanExample: public VulkanExampleBase -{ -public: - bool linkTimeOptimization = true; - - vkglTF::Model scene; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 lightPos = glm::vec4(0.0f, -2.0f, 1.0f, 0.0f); - } uniformData; - vks::Buffer uniformBuffer; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT graphicsPipelineLibraryFeatures{}; - - struct PipelineLibrary { - VkPipeline vertexInputInterface; - VkPipeline preRasterizationShaders; - VkPipeline fragmentOutputInterface; - std::vector fragmentShaders; - } pipelineLibrary; - - std::vector pipelines{}; - - struct ShaderInfo { - uint32_t* code; - size_t size; - }; - - std::mutex mutex; - VkPipelineCache threadPipelineCache{ VK_NULL_HANDLE }; - - bool newPipelineCreated = false; - - uint32_t splitX{ 2 }; - uint32_t splitY{ 2 }; - - std::vector colors{}; - float rotation{ 0.0f }; - - VulkanExample() : VulkanExampleBase() - { - title = "Graphics pipeline library"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -2.0f)); - camera.setRotation(glm::vec3(-25.0f, 15.0f, 0.0f)); - camera.setRotationSpeed(0.5f); - - // Enable required extensions - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); - - // Enable required extension features - graphicsPipelineLibraryFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT; - graphicsPipelineLibraryFeatures.graphicsPipelineLibrary = VK_TRUE; - deviceCreatepNextChain = &graphicsPipelineLibraryFeatures; - } - - ~VulkanExample() - { - if (device) { - for (auto pipeline : pipelines) { - vkDestroyPipeline(device, pipeline, nullptr); - } - for (auto pipeline : pipelineLibrary.fragmentShaders) { - vkDestroyPipeline(device, pipeline, nullptr); - } - vkDestroyPipeline(device, pipelineLibrary.fragmentOutputInterface, nullptr); - vkDestroyPipeline(device, pipelineLibrary.preRasterizationShaders, nullptr); - vkDestroyPipeline(device, pipelineLibrary.vertexInputInterface, nullptr); - vkDestroyPipelineCache(device, threadPipelineCache, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - scene.bindBuffers(drawCmdBuffers[i]); - - // Render a viewport for each pipeline - float w = (float)width / (float)splitX; - float h = (float)height / (float)splitY; - uint32_t idx = 0; - for (uint32_t y = 0; y < splitX; y++) { - for (uint32_t x = 0; x < splitY; x++) { - VkViewport viewport{}; - viewport.x = w * (float)x; - viewport.y = h * (float)y; - viewport.width = w; - viewport.height = h; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor{}; - scissor.extent.width = (uint32_t)w; - scissor.extent.height = (uint32_t)h; - scissor.offset.x = (uint32_t)w * x; - scissor.offset.y = (uint32_t)h * y; - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - if (pipelines.size() > idx) { - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[idx]); - scene.draw(drawCmdBuffers[i]); - } - - idx++; - } - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - scene.loadFromFile(getAssetPath() + "models/color_teapot_spheres.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - // With VK_EXT_graphics_pipeline_library we don't need to create the shader module when loading it, but instead have the driver create it at linking time - // So we use a custom function that only loads the required shader information without actually creating the shader module - bool loadShaderFile(std::string fileName, ShaderInfo &shaderInfo) - { -#if defined(__ANDROID__) - // Load shader from compressed asset - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, fileName.c_str(), AASSET_MODE_STREAMING); - assert(asset); - size_t size = AAsset_getLength(asset); - assert(size > 0); - - shaderInfo.size = size; - shaderInfo.code = new uint32_t[size / 4]; - AAsset_read(asset, reinterpret_cast(shaderInfo.code), size); - AAsset_close(asset); - return true; -#else - std::ifstream is(fileName, std::ios::binary | std::ios::in | std::ios::ate); - - if (is.is_open()) - { - shaderInfo.size = is.tellg(); - is.seekg(0, std::ios::beg); - shaderInfo.code = new uint32_t[shaderInfo.size]; - is.read(reinterpret_cast(shaderInfo.code), shaderInfo.size); - is.close(); - return true; - } else { - std::cerr << "Error: Could not open shader file \"" << fileName << "\"" << "\n"; - throw std::runtime_error("Could open shader file"); - return false; - } -#endif - } - - // Create the shared pipeline parts up-front - void preparePipelineLibrary() - { - // Shared layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Create a pipeline library for the vertex input interface - { - VkGraphicsPipelineLibraryCreateInfoEXT libraryInfo{}; - libraryInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT; - libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT; - - VkPipelineVertexInputStateCreateInfo vertexInputState = *vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color }); - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - - VkGraphicsPipelineCreateInfo pipelineLibraryCI{}; - pipelineLibraryCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineLibraryCI.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; - pipelineLibraryCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineLibraryCI.pNext = &libraryInfo; - pipelineLibraryCI.pInputAssemblyState = &inputAssemblyState; - pipelineLibraryCI.pVertexInputState = &vertexInputState; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineLibraryCI, nullptr, &pipelineLibrary.vertexInputInterface)); - } - - // Creata a pipeline library for the vertex shader stage - { - VkGraphicsPipelineLibraryCreateInfoEXT libraryInfo{}; - libraryInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT; - libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT; - - VkDynamicState vertexDynamicStates[2] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR }; - - VkPipelineDynamicStateCreateInfo dynamicInfo{}; - dynamicInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamicInfo.dynamicStateCount = 2; - dynamicInfo.pDynamicStates = vertexDynamicStates; - - VkPipelineViewportStateCreateInfo viewportState = {}; - viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportState.viewportCount = 1; - viewportState.scissorCount = 1; - - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - - ShaderInfo shaderInfo{}; - loadShaderFile(getShadersPath() + "graphicspipelinelibrary/shared.vert.spv", shaderInfo); - - VkShaderModuleCreateInfo shaderModuleCI{}; - shaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shaderModuleCI.codeSize = shaderInfo.size; - shaderModuleCI.pCode = shaderInfo.code; - - VkPipelineShaderStageCreateInfo shaderStageCI{}; - shaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStageCI.pNext = &shaderModuleCI; - shaderStageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; - shaderStageCI.pName = "main"; - - VkGraphicsPipelineCreateInfo pipelineLibraryCI{}; - pipelineLibraryCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineLibraryCI.pNext = &libraryInfo; - pipelineLibraryCI.renderPass = renderPass; - pipelineLibraryCI.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; - pipelineLibraryCI.stageCount = 1; - pipelineLibraryCI.pStages = &shaderStageCI; - pipelineLibraryCI.layout = pipelineLayout; - pipelineLibraryCI.pDynamicState = &dynamicInfo; - pipelineLibraryCI.pViewportState = &viewportState; - pipelineLibraryCI.pRasterizationState = &rasterizationState; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineLibraryCI, nullptr, &pipelineLibrary.preRasterizationShaders)); - - delete[] shaderInfo.code; - } - - // Create a pipeline library for the fragment output interface - { - VkGraphicsPipelineLibraryCreateInfoEXT libraryInfo{}; - libraryInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT; - libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT; - - VkPipelineColorBlendAttachmentState blendAttachmentSstate = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentSstate); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - - VkGraphicsPipelineCreateInfo pipelineLibraryCI{}; - pipelineLibraryCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineLibraryCI.pNext = &libraryInfo; - pipelineLibraryCI.layout = pipelineLayout; - pipelineLibraryCI.renderPass = renderPass; - pipelineLibraryCI.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; - pipelineLibraryCI.pColorBlendState = &colorBlendState; - pipelineLibraryCI.pMultisampleState = &multisampleState; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineLibraryCI, nullptr, &pipelineLibrary.fragmentOutputInterface)); - } - } - - void threadFn() - { - const std::lock_guard lock(mutex); - - auto start = std::chrono::steady_clock::now(); - - prepareNewPipeline(); - newPipelineCreated = true; - - // Change viewport/draw count - if (pipelines.size() > splitX * splitY) { - splitX++; - splitY++; - } - - auto delta = std::chrono::duration_cast(std::chrono::steady_clock::now() - start); - std::cout << "Pipeline created in " << delta.count() << " microseconds\n"; - } - - // Create a new pipeline using the pipeline library and a customized fragment shader - // Used from a thread - void prepareNewPipeline() - { - // Create the fragment shader part of the pipeline library with some random options - VkGraphicsPipelineLibraryCreateInfoEXT libraryInfo{}; - libraryInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT; - libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT; - - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - - // Using the pipeline library extension, we can skip the pipeline shader module creation and directly pass the shader code to the pipeline - ShaderInfo shaderInfo{}; - loadShaderFile(getShadersPath() + "graphicspipelinelibrary/uber.frag.spv", shaderInfo); - - VkShaderModuleCreateInfo shaderModuleCI{}; - shaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shaderModuleCI.codeSize = shaderInfo.size; - shaderModuleCI.pCode = shaderInfo.code; - - VkPipelineShaderStageCreateInfo shaderStageCI{}; - shaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStageCI.pNext = &shaderModuleCI; - shaderStageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderStageCI.pName = "main"; - - // Select lighting model using a specialization constant - srand(benchmark.active ? 0 : ((unsigned int)time(NULL))); - uint32_t lighting_model = (int)(rand() % 4); - - // Each shader constant of a shader stage corresponds to one map entry - VkSpecializationMapEntry specializationMapEntry{}; - specializationMapEntry.constantID = 0; - specializationMapEntry.size = sizeof(uint32_t); - - VkSpecializationInfo specializationInfo{}; - specializationInfo.mapEntryCount = 1; - specializationInfo.pMapEntries = &specializationMapEntry; - specializationInfo.dataSize = sizeof(uint32_t); - specializationInfo.pData = &lighting_model; - - shaderStageCI.pSpecializationInfo = &specializationInfo; - - VkGraphicsPipelineCreateInfo pipelineCI{}; - pipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineCI.pNext = &libraryInfo; - pipelineCI.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; - pipelineCI.stageCount = 1; - pipelineCI.pStages = &shaderStageCI; - pipelineCI.layout = pipelineLayout; - pipelineCI.renderPass = renderPass; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pMultisampleState = &multisampleState; - VkPipeline fragmentShader = VK_NULL_HANDLE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, threadPipelineCache, 1, &pipelineCI, nullptr, &fragmentShader)); - - // Create the pipeline using the pre-built pipeline library parts - // Except for above fragment shader part all parts have been pre-built and will be re-used - std::vector libraries = { - pipelineLibrary.vertexInputInterface, - pipelineLibrary.preRasterizationShaders, - fragmentShader, - pipelineLibrary.fragmentOutputInterface }; - - // Link the library parts into a graphics pipeline - VkPipelineLibraryCreateInfoKHR pipelineLibraryCI{}; - pipelineLibraryCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR; - pipelineLibraryCI.libraryCount = static_cast(libraries.size()); - pipelineLibraryCI.pLibraries = libraries.data(); - - // If set to true, we pass VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT which will let the implementation do additional optimizations at link time - // This trades in pipeline creation time for run-time performance - bool optimized = true; - - VkGraphicsPipelineCreateInfo executablePipelineCI{}; - executablePipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - executablePipelineCI.pNext = &pipelineLibraryCI; - executablePipelineCI.layout = pipelineLayout; - if (linkTimeOptimization) - { - // If link time optimization is activated in the UI, we set the VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT flag which will let the implementation do additional optimizations at link time - // This trades in pipeline creation time for run-time performance - executablePipelineCI.flags = VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT; - } - - VkPipeline executable = VK_NULL_HANDLE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, threadPipelineCache, 1, &executablePipelineCI, nullptr, &executable)); - - pipelines.push_back(executable); - // Push fragment shader to list for deletion in the sample's destructor - pipelineLibrary.fragmentShaders.push_back(fragmentShader); - - delete[] shaderInfo.code; - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Create the vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffer, - sizeof(UniformData))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - if (!paused) { - rotation += frameTimer * 0.1f; - } - camera.setPerspective(45.0f, ((float)width / (float)splitX) / ((float)height / (float)splitY), 0.1f, 256.0f); - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view * glm::rotate(glm::mat4(1.0f), glm::radians(rotation * 360.0f), glm::vec3(0.0f, 1.0f, 0.0f)); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelineLibrary(); - buildCommandBuffers(); - - // Create a separate pipeline cache for the pipeline creation thread - VkPipelineCacheCreateInfo pipelineCachCI = {}; - pipelineCachCI.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - vkCreatePipelineCache(device, &pipelineCachCI, nullptr, &threadPipelineCache); - - // Create first pipeline using a background thread - std::thread pipelineGenerationThread(&VulkanExample::threadFn, this); - pipelineGenerationThread.detach(); - - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - if (newPipelineCreated) - { - newPipelineCreated = false; - vkQueueWaitIdle(queue); - buildCommandBuffers(); - } - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - overlay->checkBox("Link time optimization", &linkTimeOptimization); - if (overlay->button("New pipeline")) { - // Spwan a thread to create a new pipeline in the background - std::thread pipelineGenerationThread(&VulkanExample::threadFn, this); - pipelineGenerationThread.detach(); - } - } -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/hdr/hdr.cpp b/examples/hdr/hdr.cpp deleted file mode 100644 index 4687e11e..00000000 --- a/examples/hdr/hdr.cpp +++ /dev/null @@ -1,830 +0,0 @@ -/* -* Vulkan Example - High dynamic range rendering pipeline -* -* This sample implements a HDR rendering pipeline that uses a wider range of possible colors via float component image formats -* It also does a bloom filter on the HDR image -* The final output is standard definition range (SDR) -* Note: Does not make use of HDR display capability. HDR is only internally used for offscreen rendering. -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool bloom = true; - bool displaySkybox = true; - - struct { - vks::TextureCubeMap envmap; - } textures; - - struct Models { - vkglTF::Model skybox; - std::vector objects; - int32_t index{ 1 }; - } models; - std::vector modelNames{}; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelview; - glm::mat4 inverseModelview; - float exposure{ 1.0f }; - } uniformData; - vks::Buffer uniformBuffer; - - struct { - VkPipeline skybox{ VK_NULL_HANDLE }; - VkPipeline reflect{ VK_NULL_HANDLE }; - VkPipeline composition{ VK_NULL_HANDLE }; - // Bloom is a two pass filter (one pass for vertical and horizontal blur) - VkPipeline bloom[2]{ VK_NULL_HANDLE }; - } pipelines; - - struct { - VkPipelineLayout models{ VK_NULL_HANDLE }; - VkPipelineLayout composition{ VK_NULL_HANDLE }; - VkPipelineLayout bloomFilter{ VK_NULL_HANDLE }; - } pipelineLayouts; - - struct { - VkDescriptorSet object{ VK_NULL_HANDLE }; - VkDescriptorSet skybox{ VK_NULL_HANDLE }; - VkDescriptorSet composition{ VK_NULL_HANDLE }; - VkDescriptorSet bloomFilter{ VK_NULL_HANDLE }; - } descriptorSets; - - struct { - VkDescriptorSetLayout models{ VK_NULL_HANDLE }; - VkDescriptorSetLayout composition{ VK_NULL_HANDLE }; - VkDescriptorSetLayout bloomFilter{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - // Framebuffer for offscreen rendering - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory mem; - VkImageView view; - VkFormat format; - void destroy(VkDevice device) - { - vkDestroyImageView(device, view, nullptr); - vkDestroyImage(device, image, nullptr); - vkFreeMemory(device, mem, nullptr); - } - }; - struct FrameBuffer { - int32_t width, height; - VkFramebuffer frameBuffer; - FrameBufferAttachment color[2]; - FrameBufferAttachment depth; - VkRenderPass renderPass; - VkSampler sampler; - } offscreen; - - struct { - int32_t width, height; - VkFramebuffer frameBuffer; - FrameBufferAttachment color[1]; - VkRenderPass renderPass; - VkSampler sampler; - } filterPass; - - VulkanExample() : VulkanExampleBase() - { - title = "High dynamic range rendering"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -6.0f)); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.skybox, nullptr); - vkDestroyPipeline(device, pipelines.reflect, nullptr); - vkDestroyPipeline(device, pipelines.composition, nullptr); - vkDestroyPipeline(device, pipelines.bloom[0], nullptr); - vkDestroyPipeline(device, pipelines.bloom[1], nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.models, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.composition, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.bloomFilter, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.models, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.composition, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.bloomFilter, nullptr); - vkDestroyRenderPass(device, offscreen.renderPass, nullptr); - vkDestroyRenderPass(device, filterPass.renderPass, nullptr); - vkDestroyFramebuffer(device, offscreen.frameBuffer, nullptr); - vkDestroyFramebuffer(device, filterPass.frameBuffer, nullptr); - vkDestroySampler(device, offscreen.sampler, nullptr); - vkDestroySampler(device, filterPass.sampler, nullptr); - offscreen.depth.destroy(device); - offscreen.color[0].destroy(device); - offscreen.color[1].destroy(device); - filterPass.color[0].destroy(device); - uniformBuffer.destroy(); - textures.envmap.destroy(); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - { - /* - First pass: Render scene to offscreen framebuffer - */ - - std::array clearValues; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[2].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = offscreen.renderPass; - renderPassBeginInfo.framebuffer = offscreen.frameBuffer; - renderPassBeginInfo.renderArea.extent.width = offscreen.width; - renderPassBeginInfo.renderArea.extent.height = offscreen.height; - renderPassBeginInfo.clearValueCount = 3; - renderPassBeginInfo.pClearValues = clearValues.data(); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)offscreen.width, (float)offscreen.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(offscreen.width, offscreen.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - - // Skybox - if (displaySkybox) - { - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.models, 0, 1, &descriptorSets.skybox, 0, NULL); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &models.skybox.vertices.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], models.skybox.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skybox); - models.skybox.draw(drawCmdBuffers[i]); - } - - // 3D object - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.models, 0, 1, &descriptorSets.object, 0, NULL); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &models.objects[models.index].vertices.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], models.objects[models.index].indices.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.reflect); - models.objects[models.index].draw(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - /* - Second render pass: First bloom pass - */ - if (bloom) { - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - // Bloom filter - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.framebuffer = filterPass.frameBuffer; - renderPassBeginInfo.renderPass = filterPass.renderPass; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.renderArea.extent.width = filterPass.width; - renderPassBeginInfo.renderArea.extent.height = filterPass.height; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)filterPass.width, (float)filterPass.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(filterPass.width, filterPass.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.bloomFilter, 0, 1, &descriptorSets.bloomFilter, 0, NULL); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.bloom[1]); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Third render pass: Scene rendering with applied second bloom pass (when enabled) - */ - { - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - // Final composition - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.composition, 0, 1, &descriptorSets.composition, 0, NULL); - - // Scene - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.composition); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - // Bloom - if (bloom) { - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.bloom[0]); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void createAttachment(VkFormat format, VkImageUsageFlagBits usage, FrameBufferAttachment *attachment) - { - VkImageAspectFlags aspectMask = 0; - VkImageLayout imageLayout; - - attachment->format = format; - - if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) - { - aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } - if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) - { - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (format >= VK_FORMAT_D16_UNORM_S8_UINT) - aspectMask |=VK_IMAGE_ASPECT_STENCIL_BIT; - imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } - - assert(aspectMask > 0); - - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = format; - image.extent.width = offscreen.width; - image.extent.height = offscreen.height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.usage = usage | VK_IMAGE_USAGE_SAMPLED_BIT; - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &attachment->image)); - vkGetImageMemoryRequirements(device, attachment->image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &attachment->mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, attachment->image, attachment->mem, 0)); - - VkImageViewCreateInfo imageView = vks::initializers::imageViewCreateInfo(); - imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageView.format = format; - imageView.subresourceRange = {}; - imageView.subresourceRange.aspectMask = aspectMask; - imageView.subresourceRange.baseMipLevel = 0; - imageView.subresourceRange.levelCount = 1; - imageView.subresourceRange.baseArrayLayer = 0; - imageView.subresourceRange.layerCount = 1; - imageView.image = attachment->image; - VK_CHECK_RESULT(vkCreateImageView(device, &imageView, nullptr, &attachment->view)); - } - - // Prepare a new framebuffer and attachments for offscreen rendering (G-Buffer) - void prepareoffscreenfer() - { - { - offscreen.width = width; - offscreen.height = height; - - // Color attachments - - // Two floating point color buffers - createAttachment(VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &offscreen.color[0]); - createAttachment(VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &offscreen.color[1]); - // Depth attachment - createAttachment(depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &offscreen.depth); - - // Set up separate renderpass with references to the color and depth attachments - std::array attachmentDescs = {}; - - // Init attachment properties - for (uint32_t i = 0; i < 3; ++i) - { - attachmentDescs[i].samples = VK_SAMPLE_COUNT_1_BIT; - attachmentDescs[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachmentDescs[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachmentDescs[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachmentDescs[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - if (i == 2) - { - attachmentDescs[i].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachmentDescs[i].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } - else - { - attachmentDescs[i].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachmentDescs[i].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - } - - // Formats - attachmentDescs[0].format = offscreen.color[0].format; - attachmentDescs[1].format = offscreen.color[1].format; - attachmentDescs[2].format = offscreen.depth.format; - - std::vector colorReferences; - colorReferences.push_back({ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); - colorReferences.push_back({ 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); - - VkAttachmentReference depthReference = {}; - depthReference.attachment = 2; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.pColorAttachments = colorReferences.data(); - subpass.colorAttachmentCount = 2; - subpass.pDepthStencilAttachment = &depthReference; - - // Use subpass dependencies for attachment layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.pAttachments = attachmentDescs.data(); - renderPassInfo.attachmentCount = static_cast(attachmentDescs.size()); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 2; - renderPassInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &offscreen.renderPass)); - - std::array attachments; - attachments[0] = offscreen.color[0].view; - attachments[1] = offscreen.color[1].view; - attachments[2] = offscreen.depth.view; - - VkFramebufferCreateInfo fbufCreateInfo = {}; - fbufCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fbufCreateInfo.pNext = NULL; - fbufCreateInfo.renderPass = offscreen.renderPass; - fbufCreateInfo.pAttachments = attachments.data(); - fbufCreateInfo.attachmentCount = static_cast(attachments.size()); - fbufCreateInfo.width = offscreen.width; - fbufCreateInfo.height = offscreen.height; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreen.frameBuffer)); - - // Create sampler to sample from the color attachments - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_NEAREST; - sampler.minFilter = VK_FILTER_NEAREST; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 1.0f; - sampler.minLod = 0.0f; - sampler.maxLod = 1.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &offscreen.sampler)); - } - - // Bloom separable filter pass - { - filterPass.width = width; - filterPass.height = height; - - // Color attachments - - // Two floating point color buffers - createAttachment(VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &filterPass.color[0]); - - // Set up separate renderpass with references to the color and depth attachments - std::array attachmentDescs = {}; - - // Init attachment properties - attachmentDescs[0].samples = VK_SAMPLE_COUNT_1_BIT; - attachmentDescs[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachmentDescs[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachmentDescs[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachmentDescs[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachmentDescs[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachmentDescs[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - attachmentDescs[0].format = filterPass.color[0].format; - - std::vector colorReferences; - colorReferences.push_back({ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.pColorAttachments = colorReferences.data(); - subpass.colorAttachmentCount = 1; - - // Use subpass dependencies for attachment layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.pAttachments = attachmentDescs.data(); - renderPassInfo.attachmentCount = static_cast(attachmentDescs.size()); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 2; - renderPassInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &filterPass.renderPass)); - - std::array attachments; - attachments[0] = filterPass.color[0].view; - - VkFramebufferCreateInfo fbufCreateInfo = {}; - fbufCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fbufCreateInfo.pNext = NULL; - fbufCreateInfo.renderPass = filterPass.renderPass; - fbufCreateInfo.pAttachments = attachments.data(); - fbufCreateInfo.attachmentCount = static_cast(attachments.size()); - fbufCreateInfo.width = filterPass.width; - fbufCreateInfo.height = filterPass.height; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &filterPass.frameBuffer)); - - // Create sampler to sample from the color attachments - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_NEAREST; - sampler.minFilter = VK_FILTER_NEAREST; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 1.0f; - sampler.minLod = 0.0f; - sampler.maxLod = 1.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &filterPass.sampler)); - } - } - - void loadAssets() - { - // Load glTF models - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY; - models.skybox.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - std::vector filenames = { "sphere.gltf", "teapot.gltf", "torusknot.gltf", "venus.gltf" }; - modelNames = { "Sphere", "Teapot", "Torusknot", "Venus" }; - models.objects.resize(filenames.size()); - for (size_t i = 0; i < filenames.size(); i++) { - models.objects[i].loadFromFile(getAssetPath() + "models/" + filenames[i], vulkanDevice, queue, glTFLoadingFlags); - } - // Load HDR cube map - textures.envmap.loadFromFile(getAssetPath() + "textures/hdr/uffizi_cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6) - }; - const uint32_t numDescriptorSets = 4; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), numDescriptorSets); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layouts - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayoutInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutInfo, nullptr, &descriptorSetLayouts.models)); - - // Bloom filter - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - - descriptorLayoutInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutInfo, nullptr, &descriptorSetLayouts.bloomFilter)); - - - // G-Buffer composition - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - - descriptorLayoutInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutInfo, nullptr, &descriptorSetLayouts.composition)); - - // Sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.models, 1); - - // 3D object descriptor set - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.object)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.envmap.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Sky box descriptor set - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.skybox)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0,&uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.envmap.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Bloom filter - allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.bloomFilter, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.bloomFilter)); - std::vector colorDescriptors = { - vks::initializers::descriptorImageInfo(offscreen.sampler, offscreen.color[0].view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - vks::initializers::descriptorImageInfo(offscreen.sampler, offscreen.color[1].view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - }; - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.bloomFilter, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &colorDescriptors[0]), - vks::initializers::writeDescriptorSet(descriptorSets.bloomFilter, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &colorDescriptors[1]), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Composition descriptor set - allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.composition, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.composition)); - colorDescriptors = { - vks::initializers::descriptorImageInfo(offscreen.sampler, offscreen.color[0].view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - vks::initializers::descriptorImageInfo(offscreen.sampler, filterPass.color[0].view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - }; - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &colorDescriptors[0]), - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &colorDescriptors[1]), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layouts - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.models, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.models)); - - pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.bloomFilter, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.bloomFilter)); - - pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.composition, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.composition)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.models, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - VkSpecializationInfo specializationInfo; - std::array specializationMapEntries; - - // Full screen pipelines - - // Empty vertex input state, full screen triangles are generated by the vertex shader - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCI.pVertexInputState = &emptyInputState; - - // Final fullscreen composition pass pipeline - std::vector blendAttachmentStates = { - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - }; - pipelineCI.layout = pipelineLayouts.composition; - pipelineCI.renderPass = renderPass; - rasterizationState.cullMode = VK_CULL_MODE_NONE; - colorBlendState.attachmentCount = 1; - colorBlendState.pAttachments = blendAttachmentStates.data(); - shaderStages[0] = loadShader(getShadersPath() + "hdr/composition.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "hdr/composition.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.composition)); - - // Bloom pass - shaderStages[0] = loadShader(getShadersPath() + "hdr/bloom.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "hdr/bloom.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - colorBlendState.pAttachments = &blendAttachmentState; - blendAttachmentState.colorWriteMask = 0xF; - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; - - // Set constant parameters via specialization constants - specializationMapEntries[0] = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t)); - uint32_t dir = 1; - specializationInfo = vks::initializers::specializationInfo(1, specializationMapEntries.data(), sizeof(dir), &dir); - shaderStages[1].pSpecializationInfo = &specializationInfo; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.bloom[0])); - - // Second blur pass (into separate framebuffer) - pipelineCI.renderPass = filterPass.renderPass; - dir = 0; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.bloom[1])); - - // Object rendering pipelines - // Use vertex input state from glTF model setup - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal }); - - blendAttachmentState.blendEnable = VK_FALSE; - pipelineCI.layout = pipelineLayouts.models; - pipelineCI.renderPass = offscreen.renderPass; - colorBlendState.attachmentCount = 2; - colorBlendState.pAttachments = blendAttachmentStates.data(); - shaderStages[0] = loadShader(getShadersPath() + "hdr/gbuffer.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "hdr/gbuffer.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Set constant parameters via specialization constants - specializationMapEntries[0] = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t)); - uint32_t shadertype = 0; - specializationInfo = vks::initializers::specializationInfo(1, specializationMapEntries.data(), sizeof(shadertype), &shadertype); - shaderStages[0].pSpecializationInfo = &specializationInfo; - shaderStages[1].pSpecializationInfo = &specializationInfo; - // Skybox pipeline (background cube) - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.skybox)); - - // Object rendering pipeline - shadertype = 1; - // Enable depth test and write - depthStencilState.depthWriteEnable = VK_TRUE; - depthStencilState.depthTestEnable = VK_TRUE; - // Flip cull mode - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.reflect)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(uniformData))); - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelview = camera.matrices.view; - uniformData.inverseModelview = glm::inverse(camera.matrices.view); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - prepareoffscreenfer(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->comboBox("Object type", &models.index, modelNames)) { - buildCommandBuffers(); - } - overlay->inputFloat("Exposure", &uniformData.exposure, 0.025f, 3); - if (overlay->checkBox("Bloom", &bloom)) { - buildCommandBuffers(); - } - if (overlay->checkBox("Skybox", &displaySkybox)) { - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/hostimagecopy/hostimagecopy.cpp b/examples/hostimagecopy/hostimagecopy.cpp deleted file mode 100644 index cad565c5..00000000 --- a/examples/hostimagecopy/hostimagecopy.cpp +++ /dev/null @@ -1,460 +0,0 @@ -/* -* Vulkan Example - Host image copy using VK_EXT_host_image_copy -* -* This sample shows how to use host image copies to directly upload an image to the devic without having to use staging - -* Copyright (C) 2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" -#include -#include - -class VulkanExample : public VulkanExampleBase -{ -public: - // Pointers for functions added by the host image copy extension; - PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT{ nullptr }; - PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT{ nullptr }; - // Used to check feature image format support for host image copies - PFN_vkGetPhysicalDeviceFormatProperties2 vkGetPhysicalDeviceFormatProperties2{ nullptr }; - - VkPhysicalDeviceHostImageCopyFeaturesEXT enabledPhysicalDeviceHostImageCopyFeaturesEXT{}; - - // Contains all Vulkan objects that are required to store and use a texture - struct Texture { - VkSampler sampler{ VK_NULL_HANDLE }; - VkImage image{ VK_NULL_HANDLE }; - VkDeviceMemory deviceMemory{ VK_NULL_HANDLE }; - VkImageView view{ VK_NULL_HANDLE }; - uint32_t width{ 0 }; - uint32_t height{ 0 }; - uint32_t mipLevels{ 0 }; - } texture; - - vkglTF::Model plane; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 viewPos; - float lodBias = 0.0f; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Host image copy"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -1.5f)); - camera.setRotation(glm::vec3(0.0f, 15.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - - // Enable required extensions - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME); - - // Enable host image copy feature - enabledPhysicalDeviceHostImageCopyFeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT; - enabledPhysicalDeviceHostImageCopyFeaturesEXT.hostImageCopy = VK_TRUE; - deviceCreatepNextChain = &enabledPhysicalDeviceHostImageCopyFeaturesEXT; - } - - ~VulkanExample() override - { - if (device) { - destroyTextureImage(texture); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - // Enable physical device features required for this example - void getEnabledFeatures() override - { - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - }; - } - - /* - Upload texture image data to the GPU - - Unlike the texture(3d/array/etc) samples, this one uses the VK_EXT_host_image_copy to drasticly simplify the process - of uploading an image from the host to the GPU. This new extension adds a way of directly uploading image data from - host memory to an optimal tiled image on the device (GPU). This no longer requires a staging buffer in between, as we can - now directly copy data stored in host memory to the image. The extension also adds new functionality to simplfy image barriers - */ - void loadTexture() - { - // We use the Khronos texture format (https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/) - std::string filename = getAssetPath() + "textures/metalplate01_rgba.ktx"; - - ktxResult result; - ktxTexture* ktxTexture; - -#if defined(__ANDROID__) - // Textures are stored inside the apk on Android (compressed) - // So they need to be loaded via the asset manager - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); - if (!asset) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - size_t size = AAsset_getLength(asset); - assert(size > 0); - - ktx_uint8_t *textureData = new ktx_uint8_t[size]; - AAsset_read(asset, textureData, size); - AAsset_close(asset); - result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); - delete[] textureData; -#else - if (!vks::tools::fileExists(filename)) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); -#endif - assert(result == KTX_SUCCESS); - - // Get properties required for using and upload texture data from the ktx texture object - texture.width = ktxTexture->baseWidth; - texture.height = ktxTexture->baseHeight; - texture.mipLevels = ktxTexture->numLevels; - ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); - - const VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM; - - // Check if the image format supports the host image copy flag - // Note: All formats that support sampling are required to support this flag - // So for the format used here (R8G8B8A8_UNORM) we could skip this check - // The flag we need to check is an extension flag, so we need to go through VkFormatProperties3 - VkFormatProperties3 formatProperties3{}; - formatProperties3.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR; - // Properties3 need to be chained into Properties2 - VkFormatProperties2 formatProperties2{}; - formatProperties2.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; - formatProperties2.pNext = &formatProperties3; - vkGetPhysicalDeviceFormatProperties2(physicalDevice, imageFormat, &formatProperties2); - - if ((formatProperties3.optimalTilingFeatures & VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0) { - vks::tools::exitFatal("The selected image format does not support the required host transfer bit.", -1); - } - - // Create optimal tiled target image on the device - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = imageFormat; - imageCreateInfo.mipLevels = texture.mipLevels; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.extent = { texture.width, texture.height, 1 }; - // For images that use host image copy we need to specify the VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT usage flag - imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &texture.image)); - - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs = {}; - vkGetImageMemoryRequirements(device, texture.image, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &texture.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, texture.image, texture.deviceMemory, 0)); - - // With host image copy we can directly copy from the KTX image in host memory to the device - // This is pretty straight forward, as the KTX image is already tightly packed, doesn't need and swizzle and as such matches - // what the device expects - - // Set up copy information for all mip levels stored in the image - std::vector memoryToImageCopies{}; - for (uint32_t i = 0; i < texture.mipLevels; i++) { - // Setup a buffer image copy structure for the current mip level - VkMemoryToImageCopyEXT memoryToImageCopy = {}; - memoryToImageCopy.sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT; - memoryToImageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - memoryToImageCopy.imageSubresource.mipLevel = i; - memoryToImageCopy.imageSubresource.baseArrayLayer = 0; - memoryToImageCopy.imageSubresource.layerCount = 1; - memoryToImageCopy.imageExtent.width = ktxTexture->baseWidth >> i; - memoryToImageCopy.imageExtent.height = ktxTexture->baseHeight >> i; - memoryToImageCopy.imageExtent.depth = 1; - - // This tells the implementation where to read the data from - // As the KTX file is tightly packed, we can simply offset into that buffer for the current mip level - ktx_size_t offset; - KTX_error_code ret = ktxTexture_GetImageOffset(ktxTexture, i, 0, 0, &offset); - assert(ret == KTX_SUCCESS); - memoryToImageCopy.pHostPointer = ktxTextureData + offset; - - memoryToImageCopies.push_back(memoryToImageCopy); - } - - VkImageSubresourceRange subresourceRange{}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = texture.mipLevels; - subresourceRange.layerCount = 1; - - // VK_EXT_host_image_copy als introduces a simplified way of doing the required image transition on the host - // This no longer requires a dedicated command buffer to submit the barrier - // We also no longer need multiple transitions, and only have to do one for the final layout - VkHostImageLayoutTransitionInfoEXT hostImageLayoutTransitionInfo{}; - hostImageLayoutTransitionInfo.sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT; - hostImageLayoutTransitionInfo.image = texture.image; - hostImageLayoutTransitionInfo.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - hostImageLayoutTransitionInfo.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - hostImageLayoutTransitionInfo.subresourceRange = subresourceRange; - - vkTransitionImageLayoutEXT(device, 1, &hostImageLayoutTransitionInfo); - - // With the image in the correct layout and copy information for all mip levels setup, we can now issue the copy to our taget image from the host - // The implementation will then convert this to an implementation specific optimal tiling layout - VkCopyMemoryToImageInfoEXT copyMemoryInfo{}; - copyMemoryInfo.sType = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT; - copyMemoryInfo.dstImage = texture.image; - copyMemoryInfo.dstImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - copyMemoryInfo.regionCount = static_cast(memoryToImageCopies.size()); - copyMemoryInfo.pRegions = memoryToImageCopies.data(); - - vkCopyMemoryToImageEXT(device, ©MemoryInfo); - - ktxTexture_Destroy(ktxTexture); - - // Create a texture sampler - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler.mipLodBias = 0.0f; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = (float)texture.mipLevels; - sampler.maxAnisotropy = vulkanDevice->properties.limits.maxSamplerAnisotropy; - sampler.anisotropyEnable = VK_TRUE; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &texture.sampler)); - - // Create image view - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.format = imageFormat; - view.subresourceRange = subresourceRange; - view.image = texture.image; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &texture.view)); - } - - // Free all Vulkan resources used by a texture object - void destroyTextureImage(Texture texture) - { - vkDestroyImageView(device, texture.view, nullptr); - vkDestroyImage(device, texture.image, nullptr); - vkDestroySampler(device, texture.sampler, nullptr); - vkFreeMemory(device, texture.deviceMemory, nullptr); - } - - void buildCommandBuffers() override - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - plane.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - // Setup a descriptor image info for the current texture to be used as a combined image sampler - VkDescriptorImageInfo textureDescriptor; - textureDescriptor.imageView = texture.view; - textureDescriptor.sampler = texture.sampler; - textureDescriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Fragment shader texture sampler - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textureDescriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - // Shaders - std::array shaderStages = { - loadShader(getShadersPath() + "texture/texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "texture/texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - pipelineCreateInfo.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Normal }); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(uniformData), &uniformData)); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - uniformData.viewPos = camera.viewPos; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - plane.loadFromFile(getAssetPath() + "models/plane_z.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void prepare() override - { - VulkanExampleBase::prepare(); - - // Get the function pointers required host image copies - vkCopyMemoryToImageEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCopyMemoryToImageEXT")); - vkTransitionImageLayoutEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkTransitionImageLayoutEXT")); - vkGetPhysicalDeviceFormatProperties2 = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2KHR")); - - loadAssets(); - loadTexture(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void render() override - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - void OnUpdateUIOverlay(vks::UIOverlay *overlay) override - { - if (overlay->header("Settings")) { - if (overlay->sliderFloat("LOD bias", &uniformData.lodBias, 0.0f, (float)texture.mipLevels)) { - updateUniformBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/imgui/main.cpp b/examples/imgui/main.cpp index 3b612ad3..4a1a6e40 100644 --- a/examples/imgui/main.cpp +++ b/examples/imgui/main.cpp @@ -1,25 +1,1002 @@ /* -* Vulkan Example - imGui (https://github.com/ocornut/imgui) -* -* Copyright (C) 2017-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + * + * Based on Vulkan examples by Sascha Willems (MIT License) + */ #include #include "vulkanexamplebase.h" #include "VulkanglTFModel.h" +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + + +// Enhanced Camera System with Maya-style controls +class OrbitCamera { +public: + // Constructor + OrbitCamera(glm::vec3 initialPosition = glm::vec3(0.0f, 0.0f, 8.0f), + glm::vec3 focusPoint = glm::vec3(0.0f, 0.0f, 0.0f)) { + m_currentFocusPoint = focusPoint; + m_targetFocusPoint = focusPoint; + + // Calculate initial spherical coordinates from position + glm::vec3 offset = initialPosition - focusPoint; + m_currentDistance = glm::length(offset); + m_targetDistance = m_currentDistance; + + // Calculate initial angles + CartesianToSpherical(initialPosition, focusPoint, m_currentDistance, m_currentAzimuth, m_currentElevation); + m_targetAzimuth = m_currentAzimuth; + m_targetElevation = m_currentElevation; + + m_currentPosition = initialPosition; + + // Set default parameters + m_fov = 45.0f; + m_smoothingFactor = 0.1f; + m_orbitSensitivity = 0.5f; + m_panSensitivity = 0.00003f; + m_zoomSensitivity = 0.1f; + + // Set constraints + m_minDistance = 0.5f; + m_maxDistance = 100.0f; + m_minElevation = -89.0f; + m_maxElevation = 89.0f; + + m_viewMatrixDirty = true; + } + + // Core camera operations + void Orbit(float deltaAzimuth, float deltaElevation, float deltaTime) { + // Apply input to target angles (convert degrees to radians) + m_targetAzimuth += glm::radians(deltaAzimuth * m_orbitSensitivity); + m_targetElevation += glm::radians(deltaElevation * m_orbitSensitivity); + ClampConstraints(); + } + + void Pan(float deltaX, float deltaY, float deltaTime) { + // Get camera's right and up vectors for screen-space panning (like legacy) + glm::mat4 viewMatrix = GetViewMatrix(); + glm::vec3 right = glm::vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]); + glm::vec3 up = glm::vec3(viewMatrix[0][1], viewMatrix[1][1], viewMatrix[2][1]); + + // Scale pan speed by distance to focus point for consistent behavior (like legacy) + float panScale = m_currentDistance * m_panSensitivity; + + // Move focus point (like legacy) + glm::vec3 panOffset = right * deltaX * panScale + up * deltaY * panScale; + m_targetFocusPoint += panOffset; + } + + void Zoom(float deltaDistance, float deltaTime) { + // Apply zoom with distance-based scaling for consistent behavior (like legacy) + m_targetDistance += deltaDistance * m_zoomSensitivity * m_currentDistance * 0.1f; + m_targetDistance = glm::clamp(m_targetDistance, m_minDistance, m_maxDistance); + } + + void ZoomImmediate(float deltaDistance, float deltaTime) { + // Apply zoom with immediate response (no smoothing/velocity) + float zoomAmount = deltaDistance * m_zoomSensitivity * m_currentDistance * 0.1f; + + // Set both target AND current immediately (no smoothing) + m_targetDistance += zoomAmount; + m_targetDistance = glm::clamp(m_targetDistance, m_minDistance, m_maxDistance); + m_currentDistance = m_targetDistance; + m_viewMatrixDirty = true; + } + + void Update(float deltaTime) { + // Smooth interpolation towards target values + float lerpFactor = 1.0f - std::pow(m_smoothingFactor, deltaTime); + + m_currentDistance = glm::mix(m_currentDistance, m_targetDistance, lerpFactor); + m_currentAzimuth = LerpAngle(m_currentAzimuth, m_targetAzimuth, lerpFactor); + m_currentElevation = glm::mix(m_currentElevation, m_targetElevation, lerpFactor); + m_currentFocusPoint = glm::mix(m_currentFocusPoint, m_targetFocusPoint, lerpFactor); + + UpdatePosition(); + } + + // Matrix access + glm::mat4 GetViewMatrix() const { + if (m_viewMatrixDirty) { + m_viewMatrix = glm::lookAt(m_currentPosition, m_currentFocusPoint, glm::vec3(0.0f, 1.0f, 0.0f)); + m_viewMatrixDirty = false; + } + return m_viewMatrix; + } + + glm::mat4 GetProjectionMatrix(float aspectRatio, float nearPlane = 0.1f, float farPlane = 256.0f) const { + return glm::perspective(glm::radians(m_fov), aspectRatio, nearPlane, farPlane); + } + + // Getters + glm::vec3 GetPosition() const { return m_currentPosition; } + glm::vec3 GetFocusPoint() const { return m_currentFocusPoint; } + float GetDistance() const { return m_currentDistance; } + float GetFOV() const { return m_fov; } + + // Focus functionality + void SetFocusToSelection(glm::vec3 selectionCenter, float selectionRadius = 1.0f) { + m_targetFocusPoint = selectionCenter; + + // Adjust distance based on selection size + if (selectionRadius > 0.0f) { + float recommendedDistance = selectionRadius * 3.0f; // Good viewing distance + recommendedDistance = glm::clamp(recommendedDistance, m_minDistance, m_maxDistance); + m_targetDistance = recommendedDistance; + } + + std::cout << "OrbitCamera: Focus set to selection at (" + << selectionCenter.x << ", " << selectionCenter.y << ", " << selectionCenter.z + << ") with radius " << selectionRadius << std::endl; + } + + void FrameAll(glm::vec3 sceneCenter, float sceneRadius) { + SetFocusToSelection(sceneCenter, sceneRadius); + } + + // Configuration + void SetSensitivity(float orbitSens, float panSens, float zoomSens) { + m_orbitSensitivity = orbitSens; + m_panSensitivity = panSens; + m_zoomSensitivity = zoomSens; + } + + void SetSmoothingFactor(float factor) { + m_smoothingFactor = glm::clamp(factor, 0.0f, 1.0f); + } + + // Immediate (non-smoothed) operations for F key focus + void SetFocusPointImmediate(glm::vec3 focusPoint) { + m_targetFocusPoint = focusPoint; + m_currentFocusPoint = focusPoint; // Immediate change, no smoothing + m_viewMatrixDirty = true; + } + + void SetDistanceImmediate(float distance) { + m_targetDistance = glm::clamp(distance, m_minDistance, m_maxDistance); + m_currentDistance = m_targetDistance; // Immediate change, no smoothing + UpdatePosition(); + m_viewMatrixDirty = true; + } + + void SetFocusToSelectionImmediate(glm::vec3 selectionCenter, float selectionRadius = 1.0f) { + SetFocusPointImmediate(selectionCenter); + + // Adjust distance based on selection size + if (selectionRadius > 0.0f) { + float recommendedDistance = selectionRadius * 3.0f; // Good viewing distance + recommendedDistance = glm::clamp(recommendedDistance, m_minDistance, m_maxDistance); + SetDistanceImmediate(recommendedDistance); + } + + std::cout << "OrbitCamera: Focus set immediately to selection at (" + << selectionCenter.x << ", " << selectionCenter.y << ", " << selectionCenter.z + << ") with radius " << selectionRadius << std::endl; + } + + void FrameAllImmediate(glm::vec3 sceneCenter, float sceneRadius) { + SetFocusPointImmediate(sceneCenter); + + // Calculate distance needed to frame the scene + float distance = sceneRadius / glm::tan(glm::radians(m_fov * 0.5f)) * 1.5f; // 1.5x padding + SetDistanceImmediate(distance); + } + + void PanImmediate(float deltaX, float deltaY, float deltaTime) { + // Get camera's right and up vectors for screen-space panning (like Pan method) + glm::mat4 viewMatrix = GetViewMatrix(); + glm::vec3 right = glm::vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]); + glm::vec3 up = glm::vec3(viewMatrix[0][1], viewMatrix[1][1], viewMatrix[2][1]); + + // Scale pan speed by distance to focus point for consistent behavior + float panScale = m_currentDistance * m_panSensitivity; + + // Calculate pan offset + glm::vec3 panOffset = right * deltaX * panScale + up * deltaY * panScale; + + // Set both target AND current immediately (no smoothing) + m_targetFocusPoint += panOffset; + m_currentFocusPoint += panOffset; + m_viewMatrixDirty = true; + } + +private: + // Current state (interpolated) + glm::vec3 m_currentPosition; + glm::vec3 m_currentFocusPoint; + float m_currentDistance; + float m_currentAzimuth; // Horizontal angle around focus point + float m_currentElevation; // Vertical angle (pitch) + + // Target state (immediate input response) + glm::vec3 m_targetFocusPoint; + float m_targetDistance; + float m_targetAzimuth; + float m_targetElevation; + + // Camera parameters + float m_fov; // Field of view in degrees + float m_smoothingFactor; // 0.0 = no smoothing, 1.0 = maximum smoothing + + // Sensitivity settings + float m_orbitSensitivity; + float m_panSensitivity; + float m_zoomSensitivity; + + // Constraints + float m_minDistance; + float m_maxDistance; + float m_minElevation; // In degrees + float m_maxElevation; // In degrees + + // Cached matrices to avoid recalculation + mutable glm::mat4 m_viewMatrix; + mutable bool m_viewMatrixDirty; + + // Internal methods + void UpdatePosition() { + m_currentPosition = SphericalToCartesian(m_currentDistance, m_currentAzimuth, m_currentElevation) + m_currentFocusPoint; + m_viewMatrixDirty = true; + } + + void ClampConstraints() { + m_targetDistance = glm::clamp(m_targetDistance, m_minDistance, m_maxDistance); + m_targetElevation = glm::clamp(m_targetElevation, glm::radians(m_minElevation), glm::radians(m_maxElevation)); + + // Normalize azimuth to 0-2π range + while (m_targetAzimuth > 2.0f * M_PI) m_targetAzimuth -= 2.0f * M_PI; + while (m_targetAzimuth < 0.0f) m_targetAzimuth += 2.0f * M_PI; + } + + glm::vec3 SphericalToCartesian(float distance, float azimuth, float elevation) const { + // Standard spherical coordinate conversion (input in radians) + float x = distance * glm::cos(elevation) * glm::cos(azimuth); + float y = distance * glm::sin(elevation); + float z = distance * glm::cos(elevation) * glm::sin(azimuth); + return glm::vec3(x, y, z); + } + + void CartesianToSpherical(glm::vec3 position, glm::vec3 center, float& distance, float& azimuth, float& elevation) const { + glm::vec3 offset = position - center; + distance = glm::length(offset); + + if (distance < 0.001f) { + // Very close to center, use default values + azimuth = 0.0f; + elevation = 0.0f; + return; + } + + // Normalize offset for angle calculations + glm::vec3 normalized = offset / distance; + + // Calculate azimuth (horizontal angle) - using atan for proper quadrant + azimuth = glm::atan(normalized.z, normalized.x); + + // Calculate elevation (vertical angle) - use asin but clamp input to avoid NaN + float sinElevation = glm::clamp(normalized.y, -1.0f, 1.0f); + elevation = glm::asin(sinElevation); + } + + float LerpAngle(float from, float to, float t) const { + // Handle angle wraparound for smooth interpolation (using radians) + float difference = to - from; + + // Wrap difference to [-π, π] range + if (difference > M_PI) difference -= 2.0f * M_PI; + if (difference < -M_PI) difference += 2.0f * M_PI; + + return from + difference * t; + } +}; + + +// Procedural Geometry Generation +struct ProceduralVertex { + glm::vec3 position; + glm::vec3 normal; + glm::vec3 color; +}; + +struct ProceduralShape { + std::vector vertices; + std::vector indices; + std::string name; + int type; // 0=cube, 1=sphere, 2=cylinder, 3=plane, 4=cone, 5=torus + + // Shape parameters + struct { + float width = 2.0f, height = 2.0f, depth = 2.0f; + int subdivisions = 1; + float radius = 1.0f; + int segments = 16; + float majorRadius = 1.0f, minorRadius = 0.3f; + } params; +}; + +class ProceduralGeometry { +public: + static ProceduralShape generateCube(float width = 4.0f, float height = 4.0f, float depth = 4.0f) { + ProceduralShape shape; + shape.name = "Cube"; + shape.type = 0; + shape.params.width = width; + shape.params.height = height; + shape.params.depth = depth; + + float w = width * 0.5f; + float h = height * 0.5f; + float d = depth * 0.5f; + + // Define 24 vertices (4 per face, 6 faces) with colors + shape.vertices = { + // Front face (red) + {{-w, -h, d}, {0, 0, 1}, {1, 0, 0}}, {{ w, -h, d}, {0, 0, 1}, {1, 0, 0}}, + {{ w, h, d}, {0, 0, 1}, {1, 0, 0}}, {{-w, h, d}, {0, 0, 1}, {1, 0, 0}}, + // Back face (green) + {{ w, -h, -d}, {0, 0, -1}, {0, 1, 0}}, {{-w, -h, -d}, {0, 0, -1}, {0, 1, 0}}, + {{-w, h, -d}, {0, 0, -1}, {0, 1, 0}}, {{ w, h, -d}, {0, 0, -1}, {0, 1, 0}}, + // Left face (blue) + {{-w, -h, -d}, {-1, 0, 0}, {0, 0, 1}}, {{-w, -h, d}, {-1, 0, 0}, {0, 0, 1}}, + {{-w, h, d}, {-1, 0, 0}, {0, 0, 1}}, {{-w, h, -d}, {-1, 0, 0}, {0, 0, 1}}, + // Right face (yellow) + {{ w, -h, d}, {1, 0, 0}, {1, 1, 0}}, {{ w, -h, -d}, {1, 0, 0}, {1, 1, 0}}, + {{ w, h, -d}, {1, 0, 0}, {1, 1, 0}}, {{ w, h, d}, {1, 0, 0}, {1, 1, 0}}, + // Top face (magenta) + {{-w, h, d}, {0, 1, 0}, {1, 0, 1}}, {{ w, h, d}, {0, 1, 0}, {1, 0, 1}}, + {{ w, h, -d}, {0, 1, 0}, {1, 0, 1}}, {{-w, h, -d}, {0, 1, 0}, {1, 0, 1}}, + // Bottom face (cyan) + {{-w, -h, -d}, {0, -1, 0}, {0, 1, 1}}, {{ w, -h, -d}, {0, -1, 0}, {0, 1, 1}}, + {{ w, -h, d}, {0, -1, 0}, {0, 1, 1}}, {{-w, -h, d}, {0, -1, 0}, {0, 1, 1}} + }; + + // Define indices for 12 triangles (2 per face) + shape.indices = { + 0,1,2, 0,2,3, // Front + 4,5,6, 4,6,7, // Back + 8,9,10, 8,10,11, // Left + 12,13,14, 12,14,15, // Right + 16,17,18, 16,18,19, // Top + 20,21,22, 20,22,23 // Bottom + }; + + return shape; + } + + static ProceduralShape generateSphere(float radius = 1.0f, int segments = 16) { + ProceduralShape shape; + shape.name = "Sphere"; + shape.type = 1; + shape.params.radius = radius; + shape.params.segments = segments; + + // Generate sphere vertices using spherical coordinates + for (int lat = 0; lat <= segments; ++lat) { + float theta = lat * M_PI / segments; + float sinTheta = sin(theta); + float cosTheta = cos(theta); + + for (int lon = 0; lon <= segments; ++lon) { + float phi = lon * 2 * M_PI / segments; + float sinPhi = sin(phi); + float cosPhi = cos(phi); + + glm::vec3 pos(radius * sinTheta * cosPhi, radius * cosTheta, radius * sinTheta * sinPhi); + glm::vec3 normal = glm::normalize(pos); + glm::vec3 color(0.8f, 0.8f, 0.8f); // Light gray color for sphere + + shape.vertices.push_back({pos, normal, color}); + } + } + + // Generate indices + for (int lat = 0; lat < segments; ++lat) { + for (int lon = 0; lon < segments; ++lon) { + int first = lat * (segments + 1) + lon; + int second = first + segments + 1; + + shape.indices.push_back(first); + shape.indices.push_back(second); + shape.indices.push_back(first + 1); + + shape.indices.push_back(second); + shape.indices.push_back(second + 1); + shape.indices.push_back(first + 1); + } + } + + return shape; + } + + static ProceduralShape generatePlane(float width = 2.0f, float height = 2.0f, int subdivisions = 1) { + ProceduralShape shape; + shape.name = "Plane"; + shape.type = 3; + shape.params.width = width; + shape.params.height = height; + shape.params.subdivisions = subdivisions; + + float w = width * 0.5f; + float h = height * 0.5f; + + // Simple quad for now + shape.vertices = { + {{-w, 0, -h}, {0, 1, 0}, {0.5f, 0.5f, 0.5f}}, // Gray plane + {{ w, 0, -h}, {0, 1, 0}, {0.5f, 0.5f, 0.5f}}, + {{ w, 0, h}, {0, 1, 0}, {0.5f, 0.5f, 0.5f}}, + {{-w, 0, h}, {0, 1, 0}, {0.5f, 0.5f, 0.5f}} + }; + + shape.indices = {0, 1, 2, 0, 2, 3}; + + return shape; + } + + static ProceduralShape generateGrid(float size = 10.0f, int divisions = 10) { + ProceduralShape shape; + shape.name = "Grid"; + shape.type = 6; // Grid type + shape.params.width = size; + shape.params.subdivisions = divisions; + + float step = size / divisions; + float halfSize = size * 0.5f; + + // Create grid lines (white grid) + glm::vec3 gridColor(1.0f, 1.0f, 1.0f); + for (int i = 0; i <= divisions; ++i) { + float pos = -halfSize + i * step; + + // Horizontal lines + shape.vertices.push_back({{-halfSize, 0, pos}, {0, 1, 0}, gridColor}); + shape.vertices.push_back({{ halfSize, 0, pos}, {0, 1, 0}, gridColor}); + + // Vertical lines + shape.vertices.push_back({{pos, 0, -halfSize}, {0, 1, 0}, gridColor}); + shape.vertices.push_back({{pos, 0, halfSize}, {0, 1, 0}, gridColor}); + } + + // Generate indices for lines + for (int i = 0; i < (divisions + 1) * 4; i += 2) { + shape.indices.push_back(i); + shape.indices.push_back(i + 1); + } + + return shape; + } + + static ProceduralShape generateCone(float radius = 1.0f, float height = 2.0f, int segments = 16) { + ProceduralShape shape; + shape.name = "Cone"; + shape.type = 4; // Cone type + shape.params.radius = radius; + shape.params.height = height; + shape.params.segments = segments; + + // Add tip vertex (red cone tip) + shape.vertices.push_back({{0, height * 0.5f, 0}, {0, 1, 0}, {1.0f, 0.0f, 0.0f}}); + + // Add center vertex for base (dark red) + shape.vertices.push_back({{0, -height * 0.5f, 0}, {0, -1, 0}, {0.5f, 0.0f, 0.0f}}); + + // Generate base vertices + for (int i = 0; i <= segments; ++i) { + float angle = (float)i / segments * 2.0f * M_PI; + float x = cos(angle) * radius; + float z = sin(angle) * radius; + glm::vec3 color(0.8f, 0.2f, 0.2f); // Light red + + // Base vertex + shape.vertices.push_back({{x, -height * 0.5f, z}, {0, -1, 0}, color}); + + // Side vertex (for side triangles) + glm::vec3 sideNormal = glm::normalize(glm::vec3(x, radius / height, z)); + shape.vertices.push_back({{x, -height * 0.5f, z}, sideNormal, color}); + } + + // Generate indices + // Side triangles (tip to base edge) + for (int i = 0; i < segments; ++i) { + int baseStart = 2 + segments + 1; + shape.indices.push_back(0); // tip + shape.indices.push_back(baseStart + (i + 1) * 2); + shape.indices.push_back(baseStart + i * 2); + } + + // Base triangles + for (int i = 0; i < segments; ++i) { + shape.indices.push_back(1); // center + shape.indices.push_back(2 + i); + shape.indices.push_back(2 + ((i + 1) % (segments + 1))); + } + + return shape; + } + + static ProceduralShape generateCylinder(float radius = 1.0f, float height = 2.0f, int segments = 16) { + ProceduralShape shape; + shape.name = "Cylinder"; + shape.type = 5; // Cylinder type + shape.params.radius = radius; + shape.params.height = height; + shape.params.segments = segments; + + float halfHeight = height * 0.5f; + + // Add center vertices for caps (blue cylinder) + shape.vertices.push_back({{0, halfHeight, 0}, {0, 1, 0}, {0.0f, 0.0f, 1.0f}}); // top center + shape.vertices.push_back({{0, -halfHeight, 0}, {0, -1, 0}, {0.0f, 0.0f, 1.0f}}); // bottom center + + // Generate side vertices (double for proper normals) + for (int i = 0; i <= segments; ++i) { + float angle = (float)i / segments * 2.0f * M_PI; + float x = cos(angle) * radius; + float z = sin(angle) * radius; + glm::vec3 normal = glm::normalize(glm::vec3(x, 0, z)); + glm::vec3 color(0.2f, 0.4f, 1.0f); // Light blue + + // Top vertices + shape.vertices.push_back({{x, halfHeight, z}, {0, 1, 0}, color}); // top cap + shape.vertices.push_back({{x, halfHeight, z}, normal, color}); // top side + + // Bottom vertices + shape.vertices.push_back({{x, -halfHeight, z}, {0, -1, 0}, color}); // bottom cap + shape.vertices.push_back({{x, -halfHeight, z}, normal, color}); // bottom side + } + + // Generate indices + for (int i = 0; i < segments; ++i) { + int topCapStart = 2; + int bottomCapStart = 4; + + // Top cap triangles + shape.indices.push_back(0); // top center + shape.indices.push_back(topCapStart + ((i + 1) % (segments + 1)) * 4); + shape.indices.push_back(topCapStart + i * 4); + + // Bottom cap triangles + shape.indices.push_back(1); // bottom center + shape.indices.push_back(bottomCapStart + i * 4); + shape.indices.push_back(bottomCapStart + ((i + 1) % (segments + 1)) * 4); + + // Side quads (as two triangles) + int topSide1 = topCapStart + 1 + i * 4; + int topSide2 = topCapStart + 1 + ((i + 1) % (segments + 1)) * 4; + int bottomSide1 = bottomCapStart + 1 + i * 4; + int bottomSide2 = bottomCapStart + 1 + ((i + 1) % (segments + 1)) * 4; + + // First triangle + shape.indices.push_back(topSide1); + shape.indices.push_back(bottomSide1); + shape.indices.push_back(topSide2); + + // Second triangle + shape.indices.push_back(topSide2); + shape.indices.push_back(bottomSide1); + shape.indices.push_back(bottomSide2); + } + + return shape; + } + + static ProceduralShape generateTorus(float majorRadius = 1.0f, float minorRadius = 0.3f, int majorSegments = 16, int minorSegments = 8) { + ProceduralShape shape; + shape.name = "Torus"; + shape.type = 6; // Torus type + shape.params.majorRadius = majorRadius; + shape.params.minorRadius = minorRadius; + shape.params.segments = majorSegments; + shape.params.subdivisions = minorSegments; + + // Generate vertices + for (int i = 0; i <= majorSegments; ++i) { + float majorAngle = (float)i / majorSegments * 2.0f * M_PI; + float cosMajor = cos(majorAngle); + float sinMajor = sin(majorAngle); + + for (int j = 0; j <= minorSegments; ++j) { + float minorAngle = (float)j / minorSegments * 2.0f * M_PI; + float cosMinor = cos(minorAngle); + float sinMinor = sin(minorAngle); + + // Calculate position + float x = (majorRadius + minorRadius * cosMinor) * cosMajor; + float y = minorRadius * sinMinor; + float z = (majorRadius + minorRadius * cosMinor) * sinMajor; + + // Calculate normal + glm::vec3 center(majorRadius * cosMajor, 0, majorRadius * sinMajor); + glm::vec3 position(x, y, z); + glm::vec3 normal = glm::normalize(position - center); + + // Use orange color for torus + glm::vec3 color(1.0f, 0.5f, 0.0f); + + shape.vertices.push_back({{x, y, z}, normal, color}); + } + } + + // Generate indices + for (int i = 0; i < majorSegments; ++i) { + for (int j = 0; j < minorSegments; ++j) { + int current = i * (minorSegments + 1) + j; + int next = ((i + 1) % (majorSegments + 1)) * (minorSegments + 1) + j; + + // First triangle + shape.indices.push_back(current); + shape.indices.push_back(next); + shape.indices.push_back(current + 1); + + // Second triangle + shape.indices.push_back(next); + shape.indices.push_back(next + 1); + shape.indices.push_back(current + 1); + } + } + + return shape; + } +}; + +// Simple Scene Object for basic hierarchy +struct SceneObject { + std::string name; + std::string type; + std::string subtype; // For procedural shapes (Cube, Sphere, etc.) + bool visible = true; + + // Simple geometry data (for procedural shapes) + std::vector vertices; + std::vector indices; + glm::vec3 position = {0.0f, 0.0f, 0.0f}; // Place objects at world origin + glm::vec3 rotation = {0.0f, 0.0f, 0.0f}; + glm::vec3 scale = {1.0f, 1.0f, 1.0f}; // Default unit scale + + // Procedural shape parameters (for real-time editing) + struct ProceduralParams { + // Cube parameters + float cubeWidth = 2.0f; + float cubeHeight = 2.0f; + float cubeDepth = 2.0f; + int cubeSubdivisions = 1; + + // Sphere parameters + float sphereRadius = 1.0f; + int sphereSegments = 16; + + // Cylinder parameters + float cylinderRadius = 1.0f; + float cylinderHeight = 2.0f; + int cylinderSegments = 16; + + // Cone parameters + float coneRadius = 1.0f; + float coneHeight = 2.0f; + int coneSegments = 16; + + // Plane parameters + float planeWidth = 2.0f; + float planeHeight = 2.0f; + int planeSubdivisions = 1; + + // Torus parameters + float torusMajorRadius = 1.0f; + float torusMinorRadius = 0.3f; + int torusMajorSegments = 16; + int torusMinorSegments = 8; + } proceduralParams; + + // Persistent Vulkan buffers (created once, used multiple times) + vks::Buffer vertexBuffer; + vks::Buffer indexBuffer; + bool buffersCreated = false; + + SceneObject(const std::string& objName, const std::string& objType = "Object") + : name(objName), type(objType) {} + + // Cleanup buffers when object is destroyed + void destroyBuffers(vks::VulkanDevice* device) { + if (buffersCreated) { + vertexBuffer.destroy(); + indexBuffer.destroy(); + buffersCreated = false; + } + } + + // Calculate bounding box center for camera focus + glm::vec3 getBoundingBoxCenter() const { + if (vertices.empty()) return position; + + glm::vec3 minPos = vertices[0].position; + glm::vec3 maxPos = vertices[0].position; + + for (const auto& vertex : vertices) { + minPos = glm::min(minPos, vertex.position); + maxPos = glm::max(maxPos, vertex.position); + } + + // Apply object transformation + glm::vec3 center = (minPos + maxPos) * 0.5f; + center = position + center * scale; // Simple transform (rotation not included for simplicity) + + return center; + } + + // Calculate bounding radius for camera focus + float getBoundingRadius() const { + if (vertices.empty()) return 1.0f; + + glm::vec3 center = getBoundingBoxCenter(); + float maxRadius = 0.0f; + + for (const auto& vertex : vertices) { + glm::vec3 transformedPos = position + vertex.position * scale; + float distance = glm::length(transformedPos - center); + maxRadius = std::max(maxRadius, distance); + } + + return std::max(maxRadius, 0.5f); // Minimum radius of 0.5 + } + + // Regenerate geometry based on current procedural parameters + void regenerateGeometry() { + if (type != "Procedural") return; + + ProceduralShape shape; + + if (subtype == "Cube") { + shape = ProceduralGeometry::generateCube(proceduralParams.cubeWidth, + proceduralParams.cubeHeight, + proceduralParams.cubeDepth); + } else if (subtype == "Sphere") { + shape = ProceduralGeometry::generateSphere(proceduralParams.sphereRadius, + proceduralParams.sphereSegments); + } else if (subtype == "Cylinder") { + shape = ProceduralGeometry::generateCylinder(proceduralParams.cylinderRadius, + proceduralParams.cylinderHeight, + proceduralParams.cylinderSegments); + } else if (subtype == "Cone") { + shape = ProceduralGeometry::generateCone(proceduralParams.coneRadius, + proceduralParams.coneHeight, + proceduralParams.coneSegments); + } else if (subtype == "Plane") { + shape = ProceduralGeometry::generatePlane(proceduralParams.planeWidth, + proceduralParams.planeHeight, + proceduralParams.planeSubdivisions); + } else if (subtype == "Torus") { + shape = ProceduralGeometry::generateTorus(proceduralParams.torusMajorRadius, + proceduralParams.torusMinorRadius, + proceduralParams.torusMajorSegments, + proceduralParams.torusMinorSegments); + } + + // Update geometry data + vertices = shape.vertices; + indices = shape.indices; + + // Destroy existing buffers if they exist (to handle size changes) + if (buffersCreated) { + vertexBuffer.destroy(); + indexBuffer.destroy(); + } + + // Mark buffers as needing recreation + buffersCreated = false; + } +}; + +// Simple scene management +struct SimpleSceneManager { + std::vector objects; + int selectedIndex = -1; + vks::VulkanDevice* device = nullptr; + + void addObject(const std::string& name, const std::string& type = "Procedural") { + objects.emplace_back(name, type); + selectedIndex = static_cast(objects.size() - 1); + } + + void addProceduralShape(const std::string& shapeName, const std::string& shapeType) { + std::string fullName = shapeName + " " + std::to_string(getObjectCount() + 1); + objects.emplace_back(fullName, "Procedural"); + + // Generate actual geometry based on shape type + SceneObject& newObj = objects.back(); + newObj.subtype = shapeType; // Set the shape subtype (Cube, Sphere, etc.) + + // Place all objects at world origin (0,0,0) + // Users can move them via transform controls in Inspector + newObj.position.x = 0.0f; + newObj.position.y = 0.0f; + newObj.position.z = 0.0f; + + // Initialize procedural parameters based on shape type (use regenerateGeometry to create initial geometry) + newObj.regenerateGeometry(); + + // Create Vulkan buffers for the geometry (delayed until first render) + // createBuffersForObject(newObj); + + selectedIndex = static_cast(objects.size() - 1); + } + + void createBuffersForObject(SceneObject& obj) { + // Enhanced validation + if (!device) { + std::cout << "Error: Device not available for buffer creation" << std::endl; + return; + } + + if (obj.vertices.empty() || obj.indices.empty()) { + std::cout << "Error: Cannot create buffers for " << obj.name << " - geometry data is empty" << std::endl; + return; + } + + if (obj.buffersCreated) { + std::cout << "Info: Buffers already created for " << obj.name << std::endl; + return; + } + + // Validate geometry data size + if (obj.vertices.size() > 1000000 || obj.indices.size() > 3000000) { + std::cout << "Warning: Large geometry for " << obj.name << " - vertices: " << obj.vertices.size() << ", indices: " << obj.indices.size() << std::endl; + } + + try { + std::cout << "Creating buffers for " << obj.name << " with " << obj.vertices.size() << " vertices and " << obj.indices.size() << " indices" << std::endl; + + // Create vertex buffer + VkDeviceSize vertexBufferSize = obj.vertices.size() * sizeof(ProceduralVertex); + if (vertexBufferSize == 0) { + std::cout << "Error: Zero vertex buffer size for " << obj.name << std::endl; + return; + } + + VkResult result = device->createBuffer( + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &obj.vertexBuffer, + vertexBufferSize, + (void*)obj.vertices.data() + ); + + if (result != VK_SUCCESS) { + std::cout << "Failed to create vertex buffer for " << obj.name << " - VkResult: " << result << std::endl; + return; + } + + // Validate vertex buffer creation + if (obj.vertexBuffer.buffer == VK_NULL_HANDLE) { + std::cout << "Error: Vertex buffer handle is null for " << obj.name << std::endl; + return; + } + + // Create index buffer + VkDeviceSize indexBufferSize = obj.indices.size() * sizeof(uint32_t); + if (indexBufferSize == 0) { + std::cout << "Error: Zero index buffer size for " << obj.name << std::endl; + obj.vertexBuffer.destroy(); + return; + } + + result = device->createBuffer( + VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &obj.indexBuffer, + indexBufferSize, + (void*)obj.indices.data() + ); + + if (result != VK_SUCCESS) { + std::cout << "Failed to create index buffer for " << obj.name << " - VkResult: " << result << std::endl; + obj.vertexBuffer.destroy(); + return; + } + + // Validate index buffer creation + if (obj.indexBuffer.buffer == VK_NULL_HANDLE) { + std::cout << "Error: Index buffer handle is null for " << obj.name << std::endl; + obj.vertexBuffer.destroy(); + return; + } + + obj.buffersCreated = true; + std::cout << "Successfully created buffers for " << obj.name << " (vertex: " << vertexBufferSize << " bytes, index: " << indexBufferSize << " bytes)" << std::endl; + } + catch (const std::exception& e) { + std::cout << "Exception creating buffers for " << obj.name << ": " << e.what() << std::endl; + obj.buffersCreated = false; + // Clean up any partially created buffers + if (obj.vertexBuffer.buffer != VK_NULL_HANDLE) { + obj.vertexBuffer.destroy(); + } + if (obj.indexBuffer.buffer != VK_NULL_HANDLE) { + obj.indexBuffer.destroy(); + } + } + } + + void removeObject(int index) { + if (index >= 0 && index < objects.size()) { + // Clean up buffers before removing object + objects[index].destroyBuffers(device); + objects.erase(objects.begin() + index); + if (selectedIndex >= objects.size()) { + selectedIndex = static_cast(objects.size() - 1); + } + } + } + + void clearScene() { + // Clean up all buffers before clearing + for (auto& obj : objects) { + obj.destroyBuffers(device); + } + objects.clear(); + selectedIndex = -1; + } + + int getObjectCount() const { + return static_cast(objects.size()); + } + + // Selection management + void setSelectedIndex(int index) { + if (index >= -1 && index < static_cast(objects.size())) { + selectedIndex = index; + } + } + + int getSelectedIndex() const { + return selectedIndex; + } + + SceneObject* getSelectedObject() { + if (selectedIndex >= 0 && selectedIndex < static_cast(objects.size())) { + return &objects[selectedIndex]; + } + return nullptr; + } + + bool hasSelection() const { + return selectedIndex >= 0 && selectedIndex < static_cast(objects.size()); + } + + void clearSelection() { + selectedIndex = -1; + } +} sceneManager; // Options and values to display/toggle from the UI struct UISettings { - bool displayModels = true; - bool displayLogos = true; - bool displayBackground = true; + bool displayModels = false; + bool displayBackground = false; bool animateLight = false; float lightSpeed = 0.25f; std::array frameTimes{}; float frameTimeMin = 9999.0f, frameTimeMax = 0.0f; float lightTimer = 0.0f; + bool showGrid = true; + float gridSize = 10.0f; + int gridDivisions = 10; + + // Panel visibility settings (for Windows menu) + bool showViewportPanel = true; + bool showInspectorPanel = true; + bool showSceneHierarchyPanel = true; + bool showAssetBrowserPanel = true; + bool showConsolePanel = false; // Hidden by default } uiSettings; // ---------------------------------------------------------------------------- @@ -133,11 +1110,47 @@ public: case 3: ImGui::StyleColorsLight(); break; + case 4: // Blue theme + { + ImGuiStyle& style = ImGui::GetStyle(); + style = ImGui::GetStyle(); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.0f, 0.3f, 0.8f, 0.6f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.0f, 0.4f, 1.0f, 0.8f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.0f, 0.2f, 0.6f, 0.4f); + style.Colors[ImGuiCol_Header] = ImVec4(0.0f, 0.3f, 0.7f, 0.4f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(0.0f, 1.0f, 1.0f, 1.0f); + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.05f, 0.05f, 0.15f, 0.9f); + break; + } + case 5: // Green theme + { + ImGuiStyle& style = ImGui::GetStyle(); + style = ImGui::GetStyle(); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.0f, 0.6f, 0.2f, 0.6f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.0f, 0.8f, 0.3f, 0.8f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.0f, 0.4f, 0.1f, 0.4f); + style.Colors[ImGuiCol_Header] = ImVec4(0.0f, 0.5f, 0.2f, 0.4f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(0.0f, 1.0f, 0.0f, 1.0f); + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.05f, 0.15f, 0.05f, 0.9f); + break; + } + case 6: // Purple theme + { + ImGuiStyle& style = ImGui::GetStyle(); + style = ImGui::GetStyle(); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.5f, 0.0f, 0.8f, 0.6f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.7f, 0.0f, 1.0f, 0.8f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.3f, 0.0f, 0.6f, 0.4f); + style.Colors[ImGuiCol_Header] = ImVec4(0.4f, 0.0f, 0.7f, 0.4f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(1.0f, 0.0f, 1.0f, 1.0f); + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.1f, 0.05f, 0.15f, 0.9f); + break; + } } } // Initialize all Vulkan resources used by the ui - void initResources(VkRenderPass renderPass, VkQueue copyQueue, const std::string& shadersPath) + void initResources(VkRenderPass renderPass, VkQueue copyQueue, const std::string& shadersPath, VkFormat colorFormat = VK_FORMAT_UNDEFINED, VkFormat depthFormat = VK_FORMAT_UNDEFINED) { ImGuiIO& io = ImGui::GetIO(); @@ -337,7 +1350,16 @@ public: std::array shaderStages{}; - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); + // Create pipeline - use dynamic rendering if no render pass provided + VkGraphicsPipelineCreateInfo pipelineCreateInfo; + if (renderPass == VK_NULL_HANDLE) { + // Dynamic rendering + pipelineCreateInfo = vks::initializers::pipelineCreateInfo(); + pipelineCreateInfo.layout = pipelineLayout; + } else { + // Traditional render pass + pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); + } pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; pipelineCreateInfo.pRasterizationState = &rasterizationState; @@ -366,17 +1388,102 @@ public: pipelineCreateInfo.pVertexInputState = &vertexInputState; + // Dynamic rendering create info for ImGui pipeline (only if using dynamic rendering) + VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo{}; + if (renderPass == VK_NULL_HANDLE && colorFormat != VK_FORMAT_UNDEFINED) { + pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; + pipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipelineRenderingCreateInfo.pColorAttachmentFormats = &colorFormat; + pipelineRenderingCreateInfo.depthAttachmentFormat = depthFormat; + pipelineRenderingCreateInfo.stencilAttachmentFormat = depthFormat; + // Chain into the pipeline create info + pipelineCreateInfo.pNext = &pipelineRenderingCreateInfo; + } + shaderStages[0] = example->loadShader(shadersPath + "imgui/ui.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = example->loadShader(shadersPath + "imgui/ui.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); VK_CHECK_RESULT(vkCreateGraphicsPipelines(device->logicalDevice, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); } + // Starts a new imGui frame and sets up windows and ui elements void newFrame(VulkanExampleBase *example, bool updateFrameGraph) { ImGui::NewFrame(); + // Menu Bar + if (ImGui::BeginMainMenuBar()) + { + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("New Scene", "Ctrl+N")) { + // Clear scene + sceneManager.clearScene(); + } + if (ImGui::MenuItem("Open Scene", "Ctrl+O")) { + // TODO: Implement scene loading + } + if (ImGui::MenuItem("Save Scene", "Ctrl+S")) { + // TODO: Implement scene saving + } + ImGui::Separator(); + if (ImGui::MenuItem("Exit", "Alt+F4")) { + example->prepared = false; + } + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Preferences")) + { + if (ImGui::BeginMenu("UI Theme")) + { + if (ImGui::MenuItem("Vulkan Red", nullptr, selectedStyle == 0)) { setStyle(0); selectedStyle = 0; } + if (ImGui::MenuItem("Classic", nullptr, selectedStyle == 1)) { setStyle(1); selectedStyle = 1; } + if (ImGui::MenuItem("Dark", nullptr, selectedStyle == 2)) { setStyle(2); selectedStyle = 2; } + if (ImGui::MenuItem("Light", nullptr, selectedStyle == 3)) { setStyle(3); selectedStyle = 3; } + if (ImGui::MenuItem("Blue", nullptr, selectedStyle == 4)) { setStyle(4); selectedStyle = 4; } + if (ImGui::MenuItem("Green", nullptr, selectedStyle == 5)) { setStyle(5); selectedStyle = 5; } + if (ImGui::MenuItem("Purple", nullptr, selectedStyle == 6)) { setStyle(6); selectedStyle = 6; } + ImGui::EndMenu(); + } + ImGui::Separator(); + // Viewport settings moved to dedicated Viewport panel + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Windows")) + { + ImGui::MenuItem("Scene Hierarchy", nullptr, &uiSettings.showSceneHierarchyPanel); + ImGui::MenuItem("Inspector", nullptr, &uiSettings.showInspectorPanel); + ImGui::MenuItem("Viewport", nullptr, &uiSettings.showViewportPanel); + ImGui::MenuItem("Asset Browser", nullptr, &uiSettings.showAssetBrowserPanel); + ImGui::MenuItem("Console", nullptr, &uiSettings.showConsolePanel); + ImGui::Separator(); + if (ImGui::MenuItem("Show All Panels")) { + uiSettings.showSceneHierarchyPanel = true; + uiSettings.showInspectorPanel = true; + uiSettings.showViewportPanel = true; + uiSettings.showAssetBrowserPanel = true; + uiSettings.showConsolePanel = true; + } + if (ImGui::MenuItem("Hide All Panels")) { + uiSettings.showSceneHierarchyPanel = false; + uiSettings.showInspectorPanel = false; + uiSettings.showViewportPanel = false; + uiSettings.showAssetBrowserPanel = false; + uiSettings.showConsolePanel = false; + } + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Help")) + { + if (ImGui::MenuItem("About")) { + // TODO: Show about dialog + } + ImGui::EndMenu(); + } + ImGui::EndMainMenuBar(); + } + // Init imGui windows and elements // Debug window @@ -404,29 +1511,462 @@ public: ImGui::PlotLines("Frame Times", &uiSettings.frameTimes[0], 50, 0, "", uiSettings.frameTimeMin, uiSettings.frameTimeMax, ImVec2(0, 80)); - ImGui::Text("Camera"); - ImGui::InputFloat3("position", &example->camera.position.x, 2); - ImGui::InputFloat3("rotation", &example->camera.rotation.x, 2); + ImGui::Text("Orbit Camera"); + ImGui::Text("Enhanced camera system active"); + ImGui::Separator(); + ImGui::Text("Controls:"); + ImGui::BulletText("F - Focus on selection"); + ImGui::BulletText("Alt+LMB - Orbit"); + ImGui::BulletText("Alt+MMB - Pan"); + ImGui::BulletText("Alt+RMB - Zoom"); + ImGui::BulletText("Mouse Wheel - Zoom"); - // Example settings window - ImGui::SetNextWindowPos(ImVec2(20 * example->ui.scale, 360 * example->ui.scale), ImGuiSetCond_FirstUseEver); - ImGui::SetNextWindowSize(ImVec2(300 * example->ui.scale, 200 * example->ui.scale), ImGuiSetCond_FirstUseEver); - ImGui::Begin("Example settings"); - ImGui::Checkbox("Render models", &uiSettings.displayModels); - ImGui::Checkbox("Display logos", &uiSettings.displayLogos); - ImGui::Checkbox("Display background", &uiSettings.displayBackground); - ImGui::Checkbox("Animate light", &uiSettings.animateLight); - ImGui::SliderFloat("Light speed", &uiSettings.lightSpeed, 0.1f, 1.0f); - //ImGui::ShowStyleSelector("UI style"); - if (ImGui::Combo("UI style", &selectedStyle, "Vulkan\0Classic\0Dark\0Light\0")) { - setStyle(selectedStyle); + // Simple Scene Hierarchy Panel + if (uiSettings.showSceneHierarchyPanel) { + ImGui::SetNextWindowPos(ImVec2(20 * example->ui.scale, 360 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(300 * example->ui.scale, 400 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Scene Hierarchy", &uiSettings.showSceneHierarchyPanel); + + // Header with object count + ImGui::Text("Scene Objects: %d", sceneManager.getObjectCount()); + ImGui::Separator(); + + // Render simple object list + for (int i = 0; i < sceneManager.objects.size(); i++) { + const auto& obj = sceneManager.objects[i]; + bool isSelected = (sceneManager.selectedIndex == i); + + // Object icon based on type + const char* icon = "[P]"; // Default procedural icon + if (obj.type == "Model") icon = "[M]"; + + // Visibility toggle (use object name as unique ImGui ID) + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushID(obj.name.c_str()); // Use object name for unique ImGui ID + if (ImGui::SmallButton(obj.visible ? "V" : "H")) { + // Toggle visibility (note: const_cast needed for modification) + const_cast(obj).visible = !obj.visible; + } + ImGui::PopID(); + ImGui::PopStyleColor(); + ImGui::SameLine(); + + // Selectable object name with highlighting for selected objects + if (isSelected) { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.2f, 1.0f)); // Gold color for selected + } + if (ImGui::Selectable((std::string(icon) + " " + obj.name).c_str(), isSelected)) { + sceneManager.setSelectedIndex(i); + std::cout << "Selected object: " << obj.name << std::endl; + } + if (isSelected) { + ImGui::PopStyleColor(); + } + + // Right-click context menu + if (ImGui::BeginPopupContextItem()) { + if (ImGui::MenuItem("Delete", "Del")) { + sceneManager.removeObject(i); + ImGui::EndPopup(); + break; // Exit loop since we modified the vector + } + ImGui::EndPopup(); + } } + + // Show message if scene is empty + if (sceneManager.getObjectCount() == 0) { + ImGui::Spacing(); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Scene is empty"); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Add objects from Asset Browser"); + } + + ImGui::End(); + } // End Scene Hierarchy Panel visibility check + + // Inspector Panel + if (uiSettings.showInspectorPanel) { + ImGui::SetNextWindowPos(ImVec2(1180 * example->ui.scale, 20 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(300 * example->ui.scale, 700 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Inspector", &uiSettings.showInspectorPanel); + ImGui::Text("Object Properties:"); + ImGui::Separator(); + + if (sceneManager.selectedIndex >= 0 && sceneManager.selectedIndex < sceneManager.objects.size()) { + auto& selectedObj = sceneManager.objects[sceneManager.selectedIndex]; // Non-const for editing + + // Object Header with Name and Type + ImGui::Text("Selected: %s", selectedObj.name.c_str()); + ImGui::SameLine(); + ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "(%s)", selectedObj.type.c_str()); + ImGui::Separator(); + + // Transform Section (collapsible like legacy 3D engine) + if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) { + // Position Vector3 control + float pos[3] = { selectedObj.position.x, selectedObj.position.y, selectedObj.position.z }; + if (ImGui::DragFloat3("Position", pos, 0.1f)) { + selectedObj.position = glm::vec3(pos[0], pos[1], pos[2]); + } + ImGui::SameLine(); + if (ImGui::SmallButton("Reset##pos")) { + selectedObj.position = glm::vec3(0.0f, 0.0f, 0.0f); + } + + // Rotation Vector3 control (degrees) + float rot[3] = { selectedObj.rotation.x, selectedObj.rotation.y, selectedObj.rotation.z }; + if (ImGui::DragFloat3("Rotation", rot, 1.0f, -360.0f, 360.0f)) { + selectedObj.rotation = glm::vec3(rot[0], rot[1], rot[2]); + } + ImGui::SameLine(); + if (ImGui::SmallButton("Reset##rot")) { + selectedObj.rotation = glm::vec3(0.0f, 0.0f, 0.0f); + } + + // Scale Vector3 control + float scale[3] = { selectedObj.scale.x, selectedObj.scale.y, selectedObj.scale.z }; + if (ImGui::DragFloat3("Scale", scale, 0.01f, 0.01f, 10.0f)) { + selectedObj.scale = glm::vec3(scale[0], scale[1], scale[2]); + } + ImGui::SameLine(); + if (ImGui::SmallButton("Reset##scale")) { + selectedObj.scale = glm::vec3(1.0f, 1.0f, 1.0f); // Default scale is 1.0 + } + + // Transform utilities + ImGui::Spacing(); + if (ImGui::Button("Reset All Transform")) { + selectedObj.position = glm::vec3(0.0f, 0.0f, 0.0f); + selectedObj.rotation = glm::vec3(0.0f, 0.0f, 0.0f); + selectedObj.scale = glm::vec3(1.0f, 1.0f, 1.0f); + } + } + + // Object Properties Section + if (ImGui::CollapsingHeader("Object Properties", ImGuiTreeNodeFlags_DefaultOpen)) { + // Visibility toggle + bool visible = selectedObj.visible; + if (ImGui::Checkbox("Visible", &visible)) { + selectedObj.visible = visible; + } + + // Object name editing + static char nameBuffer[256]; + strncpy_s(nameBuffer, selectedObj.name.c_str(), sizeof(nameBuffer) - 1); + if (ImGui::InputText("Name", nameBuffer, sizeof(nameBuffer))) { + selectedObj.name = std::string(nameBuffer); + } + } + + // Procedural Parameters Section (for procedural shapes) + if (selectedObj.type == "Procedural") { + if (ImGui::CollapsingHeader("Procedural Parameters", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Text("Shape Type: %s", selectedObj.subtype.c_str()); + + // Dynamic parameter controls based on shape type + bool parametersChanged = false; + + if (selectedObj.subtype == "Cube") { + ImGui::Text("Cube Parameters:"); + ImGui::Separator(); + + if (ImGui::DragFloat("Width", &selectedObj.proceduralParams.cubeWidth, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::DragFloat("Height", &selectedObj.proceduralParams.cubeHeight, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::DragFloat("Depth", &selectedObj.proceduralParams.cubeDepth, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::SliderInt("Subdivisions", &selectedObj.proceduralParams.cubeSubdivisions, 1, 10)) { + parametersChanged = true; + } + + if (ImGui::Button("Reset Cube Parameters")) { + selectedObj.proceduralParams.cubeWidth = 2.0f; + selectedObj.proceduralParams.cubeHeight = 2.0f; + selectedObj.proceduralParams.cubeDepth = 2.0f; + selectedObj.proceduralParams.cubeSubdivisions = 1; + parametersChanged = true; + } + + } else if (selectedObj.subtype == "Sphere") { + ImGui::Text("Sphere Parameters:"); + ImGui::Separator(); + + if (ImGui::DragFloat("Radius", &selectedObj.proceduralParams.sphereRadius, 0.05f, 0.1f, 5.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::SliderInt("Segments", &selectedObj.proceduralParams.sphereSegments, 4, 64)) { + parametersChanged = true; + } + + if (ImGui::Button("Reset Sphere Parameters")) { + selectedObj.proceduralParams.sphereRadius = 1.0f; + selectedObj.proceduralParams.sphereSegments = 16; + parametersChanged = true; + } + + } else if (selectedObj.subtype == "Cylinder") { + ImGui::Text("Cylinder Parameters:"); + ImGui::Separator(); + + if (ImGui::DragFloat("Radius", &selectedObj.proceduralParams.cylinderRadius, 0.05f, 0.1f, 5.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::DragFloat("Height", &selectedObj.proceduralParams.cylinderHeight, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::SliderInt("Segments", &selectedObj.proceduralParams.cylinderSegments, 3, 64)) { + parametersChanged = true; + } + + if (ImGui::Button("Reset Cylinder Parameters")) { + selectedObj.proceduralParams.cylinderRadius = 1.0f; + selectedObj.proceduralParams.cylinderHeight = 2.0f; + selectedObj.proceduralParams.cylinderSegments = 16; + parametersChanged = true; + } + + } else if (selectedObj.subtype == "Cone") { + ImGui::Text("Cone Parameters:"); + ImGui::Separator(); + + if (ImGui::DragFloat("Radius", &selectedObj.proceduralParams.coneRadius, 0.05f, 0.1f, 5.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::DragFloat("Height", &selectedObj.proceduralParams.coneHeight, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::SliderInt("Segments", &selectedObj.proceduralParams.coneSegments, 3, 64)) { + parametersChanged = true; + } + + if (ImGui::Button("Reset Cone Parameters")) { + selectedObj.proceduralParams.coneRadius = 1.0f; + selectedObj.proceduralParams.coneHeight = 2.0f; + selectedObj.proceduralParams.coneSegments = 16; + parametersChanged = true; + } + + } else if (selectedObj.subtype == "Plane") { + ImGui::Text("Plane Parameters:"); + ImGui::Separator(); + + if (ImGui::DragFloat("Width", &selectedObj.proceduralParams.planeWidth, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::DragFloat("Height", &selectedObj.proceduralParams.planeHeight, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::SliderInt("Subdivisions", &selectedObj.proceduralParams.planeSubdivisions, 1, 20)) { + parametersChanged = true; + } + + if (ImGui::Button("Reset Plane Parameters")) { + selectedObj.proceduralParams.planeWidth = 2.0f; + selectedObj.proceduralParams.planeHeight = 2.0f; + selectedObj.proceduralParams.planeSubdivisions = 1; + parametersChanged = true; + } + + } else if (selectedObj.subtype == "Torus") { + ImGui::Text("Torus Parameters:"); + ImGui::Separator(); + + if (ImGui::DragFloat("Major Radius", &selectedObj.proceduralParams.torusMajorRadius, 0.05f, 0.2f, 5.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::DragFloat("Minor Radius", &selectedObj.proceduralParams.torusMinorRadius, 0.02f, 0.05f, 2.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::SliderInt("Major Segments", &selectedObj.proceduralParams.torusMajorSegments, 3, 64)) { + parametersChanged = true; + } + if (ImGui::SliderInt("Minor Segments", &selectedObj.proceduralParams.torusMinorSegments, 3, 32)) { + parametersChanged = true; + } + + if (ImGui::Button("Reset Torus Parameters")) { + selectedObj.proceduralParams.torusMajorRadius = 1.0f; + selectedObj.proceduralParams.torusMinorRadius = 0.3f; + selectedObj.proceduralParams.torusMajorSegments = 16; + selectedObj.proceduralParams.torusMinorSegments = 8; + parametersChanged = true; + } + } + + // Regenerate geometry if parameters changed + if (parametersChanged) { + selectedObj.regenerateGeometry(); + std::cout << "Regenerated geometry for " << selectedObj.name << " (" << selectedObj.subtype << ")" << std::endl; + } + + ImGui::Spacing(); + ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "✓ Real-time parameter editing enabled"); + } + } + } else { + ImGui::Text("Selected: None"); + ImGui::Text("Select an object in the Scene Hierarchy"); + ImGui::Separator(); + } + + + + // UI Style selection is available in Preferences > UI Theme menu ImGui::End(); + } // End Inspector Panel visibility check + + // Viewport Panel - Settings for 3D viewport rendering + if (uiSettings.showViewportPanel) { + ImGui::SetNextWindowPos(ImVec2(660 * example->ui.scale, 350 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(320 * example->ui.scale, 280 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Viewport", &uiSettings.showViewportPanel); + + ImGui::Text("3D Viewport Settings:"); + ImGui::Separator(); + + // Render Mode Settings + if (ImGui::CollapsingHeader("Render Mode", ImGuiTreeNodeFlags_DefaultOpen)) + { + // TODO: Add render mode dropdown (Solid, X-Ray, etc.) when renderer supports it + ImGui::Text("Mode: Solid"); // Placeholder until render modes implemented + } + + // Grid Settings (moved from Inspector) + if (ImGui::CollapsingHeader("Grid Settings", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Checkbox("Show Grid", &uiSettings.showGrid); + if (uiSettings.showGrid) { + ImGui::DragFloat("Grid Size", &uiSettings.gridSize, 0.5f, 1.0f, 50.0f); + ImGui::DragInt("Grid Divisions", &uiSettings.gridDivisions, 1, 2, 50); + + // Grid color picker (placeholder - needs renderer integration) + static float gridColor[3] = { 0.5f, 0.5f, 0.5f }; + ImGui::ColorEdit3("Grid Color", gridColor); + } + + // Note about grid rendering implementation + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.3f, 1.0f), "Note: Grid rendering requires Vulkan renderer integration."); + ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "Settings are saved but grid is not yet rendered in viewport."); + } + + // Camera Settings + if (ImGui::CollapsingHeader("Camera", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Text("Current Camera: Orbit Camera"); + ImGui::Text("Controls:"); + ImGui::BulletText("Alt + LMB: Orbit"); + ImGui::BulletText("Alt + MMB: Pan"); + ImGui::BulletText("Alt + RMB: Zoom"); + ImGui::BulletText("Mouse Wheel: Zoom"); + ImGui::BulletText("F Key: Focus Selection"); + } + + // Selection Tools + if (ImGui::CollapsingHeader("Selection Tools")) + { + ImGui::Text("Active Tool: Rectangle Select"); + // TODO: Add gizmo tool selection when gizmos implemented + } + + // Lighting Settings (moved from Inspector panel) + if (ImGui::CollapsingHeader("Lighting", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Checkbox("Animate light", &uiSettings.animateLight); + ImGui::SliderFloat("Light speed", &uiSettings.lightSpeed, 0.1f, 1.0f); + } + + ImGui::End(); + } // End Viewport Panel visibility check + + // Asset Browser Panel + if (uiSettings.showAssetBrowserPanel) { + ImGui::SetNextWindowPos(ImVec2(20 * example->ui.scale, 780 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(600 * example->ui.scale, 220 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Asset Browser", &uiSettings.showAssetBrowserPanel); + ImGui::Text("Project Assets:"); + ImGui::Separator(); + + if (ImGui::CollapsingHeader("Procedural Shapes", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Text("Basic Geometric Shapes:"); + ImGui::Separator(); + + // Create buttons for each shape type - First row + if (ImGui::Button("Cube")) { + sceneManager.addProceduralShape("Cube", "Cube"); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural cube to the scene"); + ImGui::SameLine(); + if (ImGui::Button("Sphere")) { + sceneManager.addProceduralShape("Sphere", "Sphere"); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural sphere to the scene"); + ImGui::SameLine(); + if (ImGui::Button("Plane")) { + sceneManager.addProceduralShape("Plane", "Plane"); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural plane to the scene"); + + // Second row + if (ImGui::Button("Cone")) { + sceneManager.addProceduralShape("Cone", "Cone"); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural cone to the scene"); + ImGui::SameLine(); + if (ImGui::Button("Cylinder")) { + sceneManager.addProceduralShape("Cylinder", "Cylinder"); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural cylinder to the scene"); + ImGui::SameLine(); + if (ImGui::Button("Torus")) { + sceneManager.addProceduralShape("Torus", "Torus"); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural torus to the scene"); + } + + if (ImGui::CollapsingHeader("Models")) + { + ImGui::Text("• MobulaBirostris.gltf"); + ImGui::Text("• PolarBear.gltf"); + } + if (ImGui::CollapsingHeader("Textures")) + { + ImGui::Text("• Loading textures from glTF files..."); + } + if (ImGui::CollapsingHeader("Materials")) + { + ImGui::Text("• Default Vulkan Materials"); + } + ImGui::End(); + } // End Asset Browser Panel visibility check + + // Console Panel + if (uiSettings.showConsolePanel) { + ImGui::SetNextWindowPos(ImVec2(640 * example->ui.scale, 780 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(840 * example->ui.scale, 200 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Console", &uiSettings.showConsolePanel); + ImGui::Text("System Console:"); + ImGui::Separator(); + ImGui::Text("[INFO] ProceduralEngine - Vulkan Renderer initialized"); + ImGui::Text("[INFO] Scene loaded successfully - Ready for procedural generation"); + ImGui::Separator(); + static char inputBuf[256] = ""; + if (ImGui::InputText("Command", inputBuf, sizeof(inputBuf), ImGuiInputTextFlags_EnterReturnsTrue)) + { + // Process command + inputBuf[0] = '\0'; + } + ImGui::End(); + } // End Console Panel visibility check //SRS - ShowDemoWindow() sets its own initial position and size, cannot override here - ImGui::ShowDemoWindow(); + // ImGui::ShowDemoWindow(); // Render to generate draw buffers ImGui::Render(); @@ -544,6 +2084,12 @@ public: class VulkanExample : public VulkanExampleBase { public: + // Dynamic rendering function pointers + PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR{ VK_NULL_HANDLE }; + PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR{ VK_NULL_HANDLE }; + + VkPhysicalDeviceDynamicRenderingFeaturesKHR enabledDynamicRenderingFeaturesKHR{}; + ImGUI *imGui = nullptr; struct Models { @@ -552,11 +2098,12 @@ public: vkglTF::Model background; } models; + vks::Buffer uniformBufferVS; struct UBOVS { glm::mat4 projection; - glm::mat4 modelview; + glm::mat4 model; glm::vec4 lightPos; } uboVS; @@ -565,17 +2112,48 @@ public: VkDescriptorSetLayout descriptorSetLayout; VkDescriptorSet descriptorSet; - VulkanExample() : VulkanExampleBase() + // Procedural shapes pipeline + VkPipelineLayout proceduralPipelineLayout; + VkPipeline proceduralPipeline; + VkDescriptorSetLayout proceduralDescriptorSetLayout; + VkDescriptorSet proceduralDescriptorSet; + + // Enhanced orbit camera + OrbitCamera orbitCamera; + + // Mouse interaction state + bool mouseInteracting = false; + double lastMouseX = 0.0; + double lastMouseY = 0.0; + + VulkanExample() : VulkanExampleBase(), orbitCamera(glm::vec3(5.0f, 3.0f, 5.0f), glm::vec3(0.0f, 0.0f, -5.0f)) { - title = "User interfaces with ImGui"; + title = "ProceduralEngine - Vulkan 3D Viewport"; camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -4.8f)); + camera.setPosition(glm::vec3(0.0f, 0.0f, -8.0f)); camera.setRotation(glm::vec3(4.5f, -380.0f, 0.0f)); camera.setPerspective(45.0f, (float)width / (float)height, 0.1f, 256.0f); + // Configure orbit camera with legacy-compatible settings + orbitCamera.SetSensitivity(0.5f, 0.003f, 0.1f); // Match legacy sensitivity values + orbitCamera.SetSmoothingFactor(0.15f); // Match legacy smoothing + //SRS - Enable VK_KHR_get_physical_device_properties2 to retrieve device driver information for display enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + // Enable dynamic rendering extensions + enabledDeviceExtensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME); + + // Enable dynamic rendering features + enabledDynamicRenderingFeaturesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR; + enabledDynamicRenderingFeaturesKHR.dynamicRendering = VK_TRUE; + + deviceCreatepNextChain = &enabledDynamicRenderingFeaturesKHR; + // Don't use the ImGui overlay of the base framework in this sample settings.overlay = false; } @@ -586,39 +2164,133 @@ public: vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + vkDestroyPipeline(device, proceduralPipeline, nullptr); + vkDestroyPipelineLayout(device, proceduralPipelineLayout, nullptr); + vkDestroyDescriptorSetLayout(device, proceduralDescriptorSetLayout, nullptr); + uniformBufferVS.destroy(); delete imGui; } + void setupRenderPass() + { + // With VK_KHR_dynamic_rendering we no longer need a render pass, so skip the sample base render pass setup + renderPass = VK_NULL_HANDLE; + } + + void setupFrameBuffer() + { + // With VK_KHR_dynamic_rendering we no longer need a frame buffer, so skip the sample base framebuffer setup + } + + void renderProceduralShapes(VkCommandBuffer commandBuffer) { + // Render procedural shapes using persistent buffers + static int frameCount = 0; + frameCount++; + + for (auto& obj : sceneManager.objects) { + if (obj.type == "Procedural" && obj.visible && !obj.indices.empty() && obj.buffersCreated) { + // Calculate model matrix for this object + glm::mat4 model = glm::mat4(1.0f); + model = glm::translate(model, obj.position); + model = glm::rotate(model, glm::radians(obj.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); + model = glm::rotate(model, glm::radians(obj.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); + model = glm::rotate(model, glm::radians(obj.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); + model = glm::scale(model, obj.scale); + + // Update uniform buffer with object's model matrix while preserving camera matrices + UBOVS tempUBO; + tempUBO.projection = orbitCamera.GetProjectionMatrix((float)width / (float)height, 0.1f, 256.0f); // Use OrbitCamera projection + tempUBO.model = orbitCamera.GetViewMatrix() * model; // Combine view and model matrices + tempUBO.lightPos = uboVS.lightPos; // Preserve light position + + VK_CHECK_RESULT(uniformBufferVS.map()); + memcpy(uniformBufferVS.mapped, &tempUBO, sizeof(tempUBO)); + uniformBufferVS.unmap(); + + // Validate buffers before binding + if (obj.vertexBuffer.buffer == VK_NULL_HANDLE || obj.indexBuffer.buffer == VK_NULL_HANDLE) { + std::cout << "Warning: Invalid buffer handles for " << obj.name << std::endl; + continue; + } + + // Bind the vertex and index buffers for this object + VkBuffer vertexBuffers[] = { obj.vertexBuffer.buffer }; + VkDeviceSize offsets[] = { 0 }; + vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); + vkCmdBindIndexBuffer(commandBuffer, obj.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); + + // Draw the object + vkCmdDrawIndexed(commandBuffer, static_cast(obj.indices.size()), 1, 0, 0, 0); + } + } + } + void buildCommandBuffers() { VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.2f, 0.2f, 0.2f, 1.0f} }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - imGui->newFrame(this, (frameCounter == 0)); imGui->updateBuffers(); for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + // Dynamic rendering requires manual image layout transitions + // Prepare color attachment for rendering + vks::tools::insertImageMemoryBarrier( + drawCmdBuffers[i], + swapChain.images[i], + 0, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); + + // Prepare depth attachment for rendering + vks::tools::insertImageMemoryBarrier( + drawCmdBuffers[i], + depthStencil.image, + 0, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VkImageSubresourceRange{ VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1 }); + + // Set up rendering attachments for dynamic rendering + VkRenderingAttachmentInfoKHR colorAttachment{}; + colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; + colorAttachment.imageView = swapChain.imageViews[i]; + colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.clearValue.color = { 0.2f, 0.2f, 0.2f, 1.0f }; + + VkRenderingAttachmentInfoKHR depthStencilAttachment{}; + depthStencilAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; + depthStencilAttachment.imageView = depthStencil.view; + depthStencilAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depthStencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depthStencilAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + depthStencilAttachment.clearValue.depthStencil = { 1.0f, 0 }; + + VkRenderingInfoKHR renderingInfo{}; + renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR; + renderingInfo.renderArea = { 0, 0, width, height }; + renderingInfo.layerCount = 1; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &colorAttachment; + renderingInfo.pDepthAttachment = &depthStencilAttachment; + renderingInfo.pStencilAttachment = &depthStencilAttachment; + + // Begin dynamic rendering + vkCmdBeginRenderingKHR(drawCmdBuffers[i], &renderingInfo); VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); @@ -626,11 +2298,10 @@ public: VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - // Render scene + // Render vkglTF models with original pipeline vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - VkDeviceSize offsets[1] = { 0 }; if (uiSettings.displayBackground) { models.background.draw(drawCmdBuffers[i]); } @@ -639,16 +2310,32 @@ public: models.models.draw(drawCmdBuffers[i]); } - if (uiSettings.displayLogos) { - models.logos.draw(drawCmdBuffers[i]); - } + // Switch to procedural pipeline for procedural shapes + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, proceduralPipelineLayout, 0, 1, &proceduralDescriptorSet, 0, nullptr); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, proceduralPipeline); + + // Render procedural shapes + renderProceduralShapes(drawCmdBuffers[i]); // Render imGui if (ui.visible) { imGui->drawFrame(drawCmdBuffers[i]); } - vkCmdEndRenderPass(drawCmdBuffers[i]); + // End dynamic rendering + vkCmdEndRenderingKHR(drawCmdBuffers[i]); + + // Prepare image for presentation + vks::tools::insertImageMemoryBarrier( + drawCmdBuffers[i], + swapChain.images[i], + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + 0, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); } @@ -656,12 +2343,12 @@ public: void setupLayoutsAndDescriptors() { - // descriptor pool + // descriptor pool (increased to handle procedural pipeline too) std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); + VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 4); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); // Set layout @@ -683,6 +2370,20 @@ public: vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferVS.descriptor), }; vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); + + // Allocate procedural descriptor set (note: proceduralDescriptorSetLayout is created in prepareProceduralPipeline) + // This will be done after pipelines are prepared + } + + void setupProceduralDescriptorSet() + { + // Allocate procedural descriptor set + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &proceduralDescriptorSetLayout, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &proceduralDescriptorSet)); + std::vector writeDescriptorSets = { + vks::initializers::writeDescriptorSet(proceduralDescriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferVS.descriptor), + }; + vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); } void preparePipelines() @@ -700,7 +2401,9 @@ public: std::array shaderStages; - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); + // Create pipeline without render pass for dynamic rendering + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(); + pipelineCI.layout = pipelineLayout; pipelineCI.pInputAssemblyState = &inputAssemblyState; pipelineCI.pRasterizationState = &rasterizationState; pipelineCI.pColorBlendState = &colorBlendState; @@ -712,9 +2415,86 @@ public: pipelineCI.pStages = shaderStages.data(); pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color });; + // Dynamic rendering create info to define color, depth and stencil attachments at pipeline create time + VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo{}; + pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; + pipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipelineRenderingCreateInfo.pColorAttachmentFormats = &swapChain.colorFormat; + pipelineRenderingCreateInfo.depthAttachmentFormat = depthFormat; + pipelineRenderingCreateInfo.stencilAttachmentFormat = depthFormat; + // Chain into the pipeline create info + pipelineCI.pNext = &pipelineRenderingCreateInfo; + shaderStages[0] = loadShader(getShadersPath() + "imgui/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getShadersPath() + "imgui/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); + + // Create procedural shapes pipeline + prepareProceduralPipeline(); + } + + void prepareProceduralPipeline() + { + // Descriptor set layout for procedural shapes (uniform buffer only) + VkDescriptorSetLayoutBinding layoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); + VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(&layoutBinding, 1); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &proceduralDescriptorSetLayout)); + + // Pipeline layout + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&proceduralDescriptorSetLayout, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &proceduralPipelineLayout)); + + // Pipeline + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); + VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); + VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); + + // Vertex input for procedural shapes + VkVertexInputBindingDescription vertexInputBinding = vks::initializers::vertexInputBindingDescription(0, sizeof(ProceduralVertex), VK_VERTEX_INPUT_RATE_VERTEX); + std::vector vertexInputAttributes = { + vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Position + vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Normal + vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 6), // Color + }; + VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); + vertexInputState.vertexBindingDescriptionCount = 1; + vertexInputState.pVertexBindingDescriptions = &vertexInputBinding; + vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); + vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); + + std::array shaderStages; + + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(); + pipelineCI.layout = proceduralPipelineLayout; + pipelineCI.pInputAssemblyState = &inputAssemblyState; + pipelineCI.pRasterizationState = &rasterizationState; + pipelineCI.pColorBlendState = &colorBlendState; + pipelineCI.pMultisampleState = &multisampleState; + pipelineCI.pViewportState = &viewportState; + pipelineCI.pDepthStencilState = &depthStencilState; + pipelineCI.pDynamicState = &dynamicState; + pipelineCI.pVertexInputState = &vertexInputState; + pipelineCI.stageCount = static_cast(shaderStages.size()); + pipelineCI.pStages = shaderStages.data(); + + // Dynamic rendering create info + VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo{}; + pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; + pipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipelineRenderingCreateInfo.pColorAttachmentFormats = &swapChain.colorFormat; + pipelineRenderingCreateInfo.depthAttachmentFormat = depthFormat; + pipelineRenderingCreateInfo.stencilAttachmentFormat = depthFormat; + pipelineCI.pNext = &pipelineRenderingCreateInfo; + + shaderStages[0] = loadShader(getShadersPath() + "imgui/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getShadersPath() + "imgui/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &proceduralPipeline)); } // Prepare and initialize uniform buffer containing shader uniforms @@ -733,9 +2513,12 @@ public: void updateUniformBuffers() { - // Vertex shader - uboVS.projection = camera.matrices.perspective; - uboVS.modelview = camera.matrices.view * glm::mat4(1.0f); + // Update orbit camera + orbitCamera.Update(frameTimer); + + // Vertex shader - use OrbitCamera matrices + uboVS.projection = orbitCamera.GetProjectionMatrix((float)width / (float)height, 0.1f, 256.0f); + uboVS.model = orbitCamera.GetViewMatrix() * glm::mat4(1.0f); // Light source if (uiSettings.animateLight) { @@ -752,6 +2535,23 @@ public: void draw() { VulkanExampleBase::prepareFrame(); + + // Check if we need to create buffers for new objects + bool needsCommandBufferRebuild = false; + for (auto& obj : sceneManager.objects) { + if (obj.type == "Procedural" && !obj.buffersCreated && !obj.vertices.empty() && !obj.indices.empty()) { + // Wait for GPU to finish current operations before creating new buffers + vkDeviceWaitIdle(device); + sceneManager.createBuffersForObject(obj); + needsCommandBufferRebuild = true; + } + } + + // If new objects were added, ensure proper synchronization + if (needsCommandBufferRebuild) { + vkDeviceWaitIdle(device); + } + buildCommandBuffers(); submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; @@ -762,25 +2562,40 @@ public: void loadAssets() { const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.models.loadFromFile(getAssetPath() + "models/vulkanscenemodels.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.background.loadFromFile(getAssetPath() + "models/vulkanscenebackground.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.logos.loadFromFile(getAssetPath() + "models/vulkanscenelogos.gltf", vulkanDevice, queue, glTFLoadingFlags); + // Models available in assets but not auto-loaded + // models.models.loadFromFile(getAssetPath() + "models/MobulaBirostris.gltf", vulkanDevice, queue, glTFLoadingFlags); + // models.background.loadFromFile(getAssetPath() + "models/PolarBear.gltf", vulkanDevice, queue, glTFLoadingFlags); } void prepareImGui() { imGui = new ImGUI(this); imGui->init((float)width, (float)height); - imGui->initResources(renderPass, queue, getShadersPath()); + imGui->initResources(renderPass, queue, getShadersPath(), swapChain.colorFormat, depthFormat); } void prepare() { VulkanExampleBase::prepare(); + + // Get dynamic rendering function pointers + vkCmdBeginRenderingKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBeginRenderingKHR")); + vkCmdEndRenderingKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdEndRenderingKHR")); + + // Validate function pointers + if (!vkCmdBeginRenderingKHR || !vkCmdEndRenderingKHR) { + std::cout << "ERROR: Failed to load dynamic rendering function pointers" << std::endl; + exit(1); + } + + // Initialize scene manager with device pointer + sceneManager.device = vulkanDevice; + loadAssets(); prepareUniformBuffers(); setupLayoutsAndDescriptors(); preparePipelines(); + setupProceduralDescriptorSet(); prepareImGui(); buildCommandBuffers(); prepared = true; @@ -804,19 +2619,25 @@ public: io.MouseDown[1] = mouseState.buttons.right && ui.visible; io.MouseDown[2] = mouseState.buttons.middle && ui.visible; + // Handle mouse wheel for camera zoom + if (io.MouseWheel != 0.0f) { + orbitCamera.ZoomImmediate(-io.MouseWheel * 10.0f, frameTimer); + } + draw(); } - virtual void mouseMoved(double x, double y, bool &handled) - { - ImGuiIO& io = ImGui::GetIO(); - handled = io.WantCaptureMouse && ui.visible; - } // Input handling is platform specific, to show how it's basically done this sample implements it for Windows #if defined(_WIN32) virtual void OnHandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); + + // Handle mouse wheel for ImGui (needed for camera zoom) + if (uMsg == WM_MOUSEWHEEL) { + io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; + } + // Only react to keyboard input if ImGui is active if (io.WantCaptureKeyboard) { // Character input @@ -836,6 +2657,79 @@ public: } #endif + // Override keyPressed for F key focus functionality + virtual void keyPressed(uint32_t keyCode) override + { + // Handle F key for focus (immediate, no smoothing) + if (keyCode == KEY_F) { + if (sceneManager.hasSelection()) { + // Focus on selected object immediately + SceneObject* selectedObject = sceneManager.getSelectedObject(); + if (selectedObject) { + glm::vec3 objectCenter = selectedObject->getBoundingBoxCenter(); + float objectRadius = selectedObject->getBoundingRadius(); + orbitCamera.SetFocusToSelectionImmediate(objectCenter, objectRadius); + std::cout << "Focused camera on selected object: " << selectedObject->name << std::endl; + } + } else { + // No selection, focus on scene center immediately + orbitCamera.FrameAllImmediate(glm::vec3(0.0f, 0.0f, -5.0f), 3.0f); + std::cout << "Focused camera on scene center (no selection)" << std::endl; + } + } + + + // Call base implementation for other keys + VulkanExampleBase::keyPressed(keyCode); + } + + // Override mouseMoved for camera orbit/pan controls + virtual void mouseMoved(double x, double y, bool &handled) override + { + ImGuiIO& io = ImGui::GetIO(); + + // Calculate mouse delta + double deltaX = x - lastMouseX; + double deltaY = y - lastMouseY; + lastMouseX = x; + lastMouseY = y; + + // Handle industry-standard Maya/3ds Max style camera controls (Alt + mouse) + // Use Windows API directly for Alt key detection since ImGui's KeyAlt is not reliable in this Vulkan framework +#if defined(_WIN32) + bool altPressed = (GetAsyncKeyState(VK_MENU) & 0x8000) != 0; +#else + bool altPressed = io.KeyAlt; // Fallback for non-Windows platforms +#endif + + // Alt key detection is now working properly using Windows GetAsyncKeyState API + + if (altPressed && mouseState.buttons.left) { + // Alt + Left mouse: orbit around focus point + if (std::abs(deltaX) > 0.1 || std::abs(deltaY) > 0.1) { + orbitCamera.Orbit(deltaX * 0.5f, deltaY * 0.5f, frameTimer); + handled = true; + } + } else if (altPressed && mouseState.buttons.middle) { + // Alt + Middle mouse: pan viewport (immediate, no smoothing) + if (std::abs(deltaX) > 0.1 || std::abs(deltaY) > 0.1) { + orbitCamera.PanImmediate(-deltaX, deltaY, frameTimer); + handled = true; + } + } else if (altPressed && mouseState.buttons.right) { + // Alt + Right mouse: zoom (dolly camera) + if (std::abs(deltaY) > 0.1) { + orbitCamera.Zoom(deltaY * 0.01f, frameTimer); + handled = true; + } + } + + // Call base implementation if not handled + if (!handled) { + VulkanExampleBase::mouseMoved(x, y, handled); + } + } + }; VULKAN_EXAMPLE_MAIN() diff --git a/examples/imgui/main_backup.cpp b/examples/imgui/main_backup.cpp new file mode 100644 index 00000000..8475fcde --- /dev/null +++ b/examples/imgui/main_backup.cpp @@ -0,0 +1,1805 @@ +/* +* Vulkan Example - imGui (https://github.com/ocornut/imgui) +* +* Copyright (C) 2017-2025 by Sascha Willems - www.saschawillems.de +* +* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) +*/ + +#include +#include "vulkanexamplebase.h" +#include "VulkanglTFModel.h" +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +// Forward declaration +class VulkanExample; + +// Procedural Geometry Generation +struct ProceduralVertex { + glm::vec3 position; + glm::vec3 normal; + glm::vec2 texCoord; +}; + +struct ProceduralShape { + std::vector vertices; + std::vector indices; + std::string name; + int type; // 0=cube, 1=sphere, 2=cylinder, 3=plane, 4=cone, 5=torus + + // Shape parameters + struct { + float width = 2.0f, height = 2.0f, depth = 2.0f; + int subdivisions = 1; + float radius = 1.0f; + int segments = 16; + float majorRadius = 1.0f, minorRadius = 0.3f; + } params; +}; + +class ProceduralGeometry { +public: + static ProceduralShape generateCube(float width = 4.0f, float height = 4.0f, float depth = 4.0f) { + ProceduralShape shape; + shape.name = "Cube"; + shape.type = 0; + shape.params.width = width; + shape.params.height = height; + shape.params.depth = depth; + + float w = width * 0.5f; + float h = height * 0.5f; + float d = depth * 0.5f; + + // Define 24 vertices (4 per face, 6 faces) + shape.vertices = { + // Front face + {{-w, -h, d}, {0, 0, 1}, {0, 0}}, {{ w, -h, d}, {0, 0, 1}, {1, 0}}, + {{ w, h, d}, {0, 0, 1}, {1, 1}}, {{-w, h, d}, {0, 0, 1}, {0, 1}}, + // Back face + {{ w, -h, -d}, {0, 0, -1}, {0, 0}}, {{-w, -h, -d}, {0, 0, -1}, {1, 0}}, + {{-w, h, -d}, {0, 0, -1}, {1, 1}}, {{ w, h, -d}, {0, 0, -1}, {0, 1}}, + // Left face + {{-w, -h, -d}, {-1, 0, 0}, {0, 0}}, {{-w, -h, d}, {-1, 0, 0}, {1, 0}}, + {{-w, h, d}, {-1, 0, 0}, {1, 1}}, {{-w, h, -d}, {-1, 0, 0}, {0, 1}}, + // Right face + {{ w, -h, d}, {1, 0, 0}, {0, 0}}, {{ w, -h, -d}, {1, 0, 0}, {1, 0}}, + {{ w, h, -d}, {1, 0, 0}, {1, 1}}, {{ w, h, d}, {1, 0, 0}, {0, 1}}, + // Top face + {{-w, h, d}, {0, 1, 0}, {0, 0}}, {{ w, h, d}, {0, 1, 0}, {1, 0}}, + {{ w, h, -d}, {0, 1, 0}, {1, 1}}, {{-w, h, -d}, {0, 1, 0}, {0, 1}}, + // Bottom face + {{-w, -h, -d}, {0, -1, 0}, {0, 0}}, {{ w, -h, -d}, {0, -1, 0}, {1, 0}}, + {{ w, -h, d}, {0, -1, 0}, {1, 1}}, {{-w, -h, d}, {0, -1, 0}, {0, 1}} + }; + + // Define indices for 12 triangles (2 per face) + shape.indices = { + 0,1,2, 0,2,3, // Front + 4,5,6, 4,6,7, // Back + 8,9,10, 8,10,11, // Left + 12,13,14, 12,14,15, // Right + 16,17,18, 16,18,19, // Top + 20,21,22, 20,22,23 // Bottom + }; + + return shape; + } + + static ProceduralShape generateSphere(float radius = 1.0f, int segments = 16) { + ProceduralShape shape; + shape.name = "Sphere"; + shape.type = 1; + shape.params.radius = radius; + shape.params.segments = segments; + + // Generate sphere vertices using spherical coordinates + for (int lat = 0; lat <= segments; ++lat) { + float theta = lat * M_PI / segments; + float sinTheta = sin(theta); + float cosTheta = cos(theta); + + for (int lon = 0; lon <= segments; ++lon) { + float phi = lon * 2 * M_PI / segments; + float sinPhi = sin(phi); + float cosPhi = cos(phi); + + glm::vec3 pos(radius * sinTheta * cosPhi, radius * cosTheta, radius * sinTheta * sinPhi); + glm::vec3 normal = glm::normalize(pos); + glm::vec2 texCoord((float)lon / segments, (float)lat / segments); + + shape.vertices.push_back({pos, normal, texCoord}); + } + } + + // Generate indices + for (int lat = 0; lat < segments; ++lat) { + for (int lon = 0; lon < segments; ++lon) { + int first = lat * (segments + 1) + lon; + int second = first + segments + 1; + + shape.indices.push_back(first); + shape.indices.push_back(second); + shape.indices.push_back(first + 1); + + shape.indices.push_back(second); + shape.indices.push_back(second + 1); + shape.indices.push_back(first + 1); + } + } + + return shape; + } + + static ProceduralShape generatePlane(float width = 2.0f, float height = 2.0f, int subdivisions = 1) { + ProceduralShape shape; + shape.name = "Plane"; + shape.type = 3; + shape.params.width = width; + shape.params.height = height; + shape.params.subdivisions = subdivisions; + + float w = width * 0.5f; + float h = height * 0.5f; + + // Simple quad for now + shape.vertices = { + {{-w, 0, -h}, {0, 1, 0}, {0, 0}}, + {{ w, 0, -h}, {0, 1, 0}, {1, 0}}, + {{ w, 0, h}, {0, 1, 0}, {1, 1}}, + {{-w, 0, h}, {0, 1, 0}, {0, 1}} + }; + + shape.indices = {0, 1, 2, 0, 2, 3}; + + return shape; + } + + static ProceduralShape generateGrid(float size = 10.0f, int divisions = 10) { + ProceduralShape shape; + shape.name = "Grid"; + shape.type = 6; // Grid type + shape.params.width = size; + shape.params.subdivisions = divisions; + + float step = size / divisions; + float halfSize = size * 0.5f; + + // Create grid lines + for (int i = 0; i <= divisions; ++i) { + float pos = -halfSize + i * step; + + // Horizontal lines + shape.vertices.push_back({{-halfSize, 0, pos}, {0, 1, 0}, {0, 0}}); + shape.vertices.push_back({{ halfSize, 0, pos}, {0, 1, 0}, {1, 0}}); + + // Vertical lines + shape.vertices.push_back({{pos, 0, -halfSize}, {0, 1, 0}, {0, 0}}); + shape.vertices.push_back({{pos, 0, halfSize}, {0, 1, 0}, {1, 0}}); + } + + // Generate indices for lines + for (int i = 0; i < (divisions + 1) * 4; i += 2) { + shape.indices.push_back(i); + shape.indices.push_back(i + 1); + } + + return shape; + } + + static ProceduralShape generateCone(float radius = 1.0f, float height = 2.0f, int segments = 16) { + ProceduralShape shape; + shape.name = "Cone"; + shape.type = 4; // Cone type + shape.params.radius = radius; + shape.params.height = height; + shape.params.segments = segments; + + // Add tip vertex + shape.vertices.push_back({{0, height * 0.5f, 0}, {0, 1, 0}, {0.5f, 1.0f}}); + + // Add center vertex for base + shape.vertices.push_back({{0, -height * 0.5f, 0}, {0, -1, 0}, {0.5f, 0.0f}}); + + // Generate base vertices + for (int i = 0; i <= segments; ++i) { + float angle = (float)i / segments * 2.0f * M_PI; + float x = cos(angle) * radius; + float z = sin(angle) * radius; + float u = (cos(angle) + 1.0f) * 0.5f; + float v = (sin(angle) + 1.0f) * 0.5f; + + // Base vertex + shape.vertices.push_back({{x, -height * 0.5f, z}, {0, -1, 0}, {u, v}}); + + // Side vertex (for side triangles) + glm::vec3 sideNormal = glm::normalize(glm::vec3(x, radius / height, z)); + shape.vertices.push_back({{x, -height * 0.5f, z}, sideNormal, {(float)i / segments, 0.0f}}); + } + + // Generate indices + // Side triangles (tip to base edge) + for (int i = 0; i < segments; ++i) { + int baseStart = 2 + segments + 1; + shape.indices.push_back(0); // tip + shape.indices.push_back(baseStart + (i + 1) * 2); + shape.indices.push_back(baseStart + i * 2); + } + + // Base triangles + for (int i = 0; i < segments; ++i) { + shape.indices.push_back(1); // center + shape.indices.push_back(2 + i); + shape.indices.push_back(2 + ((i + 1) % (segments + 1))); + } + + return shape; + } + + static ProceduralShape generateCylinder(float radius = 1.0f, float height = 2.0f, int segments = 16) { + ProceduralShape shape; + shape.name = "Cylinder"; + shape.type = 5; // Cylinder type + shape.params.radius = radius; + shape.params.height = height; + shape.params.segments = segments; + + float halfHeight = height * 0.5f; + + // Add center vertices for caps + shape.vertices.push_back({{0, halfHeight, 0}, {0, 1, 0}, {0.5f, 0.5f}}); // top center + shape.vertices.push_back({{0, -halfHeight, 0}, {0, -1, 0}, {0.5f, 0.5f}}); // bottom center + + // Generate side vertices (double for proper normals) + for (int i = 0; i <= segments; ++i) { + float angle = (float)i / segments * 2.0f * M_PI; + float x = cos(angle) * radius; + float z = sin(angle) * radius; + glm::vec3 normal = glm::normalize(glm::vec3(x, 0, z)); + float u = (float)i / segments; + + // Top vertices + shape.vertices.push_back({{x, halfHeight, z}, {0, 1, 0}, {(cos(angle) + 1) * 0.5f, (sin(angle) + 1) * 0.5f}}); // top cap + shape.vertices.push_back({{x, halfHeight, z}, normal, {u, 1.0f}}); // top side + + // Bottom vertices + shape.vertices.push_back({{x, -halfHeight, z}, {0, -1, 0}, {(cos(angle) + 1) * 0.5f, (sin(angle) + 1) * 0.5f}}); // bottom cap + shape.vertices.push_back({{x, -halfHeight, z}, normal, {u, 0.0f}}); // bottom side + } + + // Generate indices + for (int i = 0; i < segments; ++i) { + int topCapStart = 2; + int bottomCapStart = 4; + + // Top cap triangles + shape.indices.push_back(0); // top center + shape.indices.push_back(topCapStart + ((i + 1) % (segments + 1)) * 4); + shape.indices.push_back(topCapStart + i * 4); + + // Bottom cap triangles + shape.indices.push_back(1); // bottom center + shape.indices.push_back(bottomCapStart + i * 4); + shape.indices.push_back(bottomCapStart + ((i + 1) % (segments + 1)) * 4); + + // Side quads (as two triangles) + int topSide1 = topCapStart + 1 + i * 4; + int topSide2 = topCapStart + 1 + ((i + 1) % (segments + 1)) * 4; + int bottomSide1 = bottomCapStart + 1 + i * 4; + int bottomSide2 = bottomCapStart + 1 + ((i + 1) % (segments + 1)) * 4; + + // First triangle + shape.indices.push_back(topSide1); + shape.indices.push_back(bottomSide1); + shape.indices.push_back(topSide2); + + // Second triangle + shape.indices.push_back(topSide2); + shape.indices.push_back(bottomSide1); + shape.indices.push_back(bottomSide2); + } + + return shape; + } + + static ProceduralShape generateTorus(float majorRadius = 1.0f, float minorRadius = 0.3f, int majorSegments = 16, int minorSegments = 8) { + ProceduralShape shape; + shape.name = "Torus"; + shape.type = 6; // Torus type + shape.params.majorRadius = majorRadius; + shape.params.minorRadius = minorRadius; + shape.params.segments = majorSegments; + shape.params.subdivisions = minorSegments; + + // Generate vertices + for (int i = 0; i <= majorSegments; ++i) { + float majorAngle = (float)i / majorSegments * 2.0f * M_PI; + float cosMajor = cos(majorAngle); + float sinMajor = sin(majorAngle); + + for (int j = 0; j <= minorSegments; ++j) { + float minorAngle = (float)j / minorSegments * 2.0f * M_PI; + float cosMinor = cos(minorAngle); + float sinMinor = sin(minorAngle); + + // Calculate position + float x = (majorRadius + minorRadius * cosMinor) * cosMajor; + float y = minorRadius * sinMinor; + float z = (majorRadius + minorRadius * cosMinor) * sinMajor; + + // Calculate normal + glm::vec3 center(majorRadius * cosMajor, 0, majorRadius * sinMajor); + glm::vec3 position(x, y, z); + glm::vec3 normal = glm::normalize(position - center); + + // Calculate UV coordinates + float u = (float)i / majorSegments; + float v = (float)j / minorSegments; + + shape.vertices.push_back({{x, y, z}, normal, {u, v}}); + } + } + + // Generate indices + for (int i = 0; i < majorSegments; ++i) { + for (int j = 0; j < minorSegments; ++j) { + int current = i * (minorSegments + 1) + j; + int next = ((i + 1) % (majorSegments + 1)) * (minorSegments + 1) + j; + + // First triangle + shape.indices.push_back(current); + shape.indices.push_back(next); + shape.indices.push_back(current + 1); + + // Second triangle + shape.indices.push_back(next); + shape.indices.push_back(next + 1); + shape.indices.push_back(current + 1); + } + } + + return shape; + } +}; + +// Hierarchical Scene Node structure (based on Sascha's gltfscenerendering) +struct SceneNode { + SceneNode* parent = nullptr; + std::vector children; + std::string name; + glm::vec3 position = {0.0f, 0.0f, 0.0f}; + glm::vec3 rotation = {0.0f, 0.0f, 0.0f}; + glm::vec3 scale = {1.0f, 1.0f, 1.0f}; + glm::mat4 matrix = glm::mat4(1.0f); + bool visible = true; + + // Procedural shape data + ProceduralShape* proceduralShape = nullptr; + bool isProceduralShape = false; + + // Object type for icons/identification + enum ObjectType { + SCENE_ROOT, + PROCEDURAL_OBJECT, + MODEL_OBJECT, + LIGHT_OBJECT, + CAMERA_OBJECT + } type = PROCEDURAL_OBJECT; + + // Constructor + SceneNode(const std::string& nodeName = "Object", ObjectType nodeType = PROCEDURAL_OBJECT) + : name(nodeName), type(nodeType) {} + + // Destructor - clean up children + ~SceneNode() { + for (auto child : children) { + delete child; + } + if (proceduralShape) { + delete proceduralShape; + } + } + + // Add child to this node + void addChild(SceneNode* child) { + if (child && child->parent != this) { + if (child->parent) { + child->parent->removeChild(child); + } + child->parent = this; + children.push_back(child); + } + } + + // Remove child from this node + void removeChild(SceneNode* child) { + auto it = std::find(children.begin(), children.end(), child); + if (it != children.end()) { + (*it)->parent = nullptr; + children.erase(it); + } + } + + // Get world transform matrix + glm::mat4 getWorldMatrix() const { + glm::mat4 nodeMatrix = matrix; + SceneNode* currentParent = parent; + while (currentParent) { + nodeMatrix = currentParent->matrix * nodeMatrix; + currentParent = currentParent->parent; + } + return nodeMatrix; + } + + // Update transform matrix from position, rotation, scale + void updateMatrix() { + matrix = glm::mat4(1.0f); + matrix = glm::translate(matrix, position); + matrix = glm::rotate(matrix, glm::radians(rotation.x), glm::vec3(1, 0, 0)); + matrix = glm::rotate(matrix, glm::radians(rotation.y), glm::vec3(0, 1, 0)); + matrix = glm::rotate(matrix, glm::radians(rotation.z), glm::vec3(0, 0, 1)); + matrix = glm::scale(matrix, scale); + } +}; + +// Scene management with hierarchical structure +struct SceneManager { + std::vector rootNodes; + SceneNode* selectedNode = nullptr; + SceneNode* sceneRoot = nullptr; + + SceneManager() { + // Create clean scene root without default categories + sceneRoot = new SceneNode("Scene", SceneNode::SCENE_ROOT); + rootNodes.push_back(sceneRoot); + } + + ~SceneManager() { + for (auto node : rootNodes) { + delete node; + } + } + + void addProceduralShape(const ProceduralShape& shape, SceneNode* parent = nullptr) { + if (!parent) { + // Add directly to scene root for flat hierarchy + parent = sceneRoot; + } + + SceneNode* newNode = new SceneNode(shape.name + " " + std::to_string(getObjectCount() + 1), SceneNode::PROCEDURAL_OBJECT); + newNode->isProceduralShape = true; + newNode->proceduralShape = new ProceduralShape(shape); + newNode->updateMatrix(); + + parent->addChild(newNode); + selectedNode = newNode; + } + + SceneNode* findNodeByName(const std::string& name) { + for (auto root : rootNodes) { + SceneNode* found = findNodeByNameRecursive(root, name); + if (found) return found; + } + return nullptr; + } + + SceneNode* findNodeByNameRecursive(SceneNode* node, const std::string& name) { + if (node->name == name) return node; + for (auto child : node->children) { + SceneNode* found = findNodeByNameRecursive(child, name); + if (found) return found; + } + return nullptr; + } + + int getObjectCount() const { + int count = 0; + for (auto root : rootNodes) { + count += getObjectCountRecursive(root); + } + return count; + } + + int getObjectCountRecursive(SceneNode* node) const { + int count = (node->type == SceneNode::PROCEDURAL_OBJECT || node->type == SceneNode::MODEL_OBJECT) ? 1 : 0; + for (auto child : node->children) { + count += getObjectCountRecursive(child); + } + return count; + } + + void deleteNode(SceneNode* node) { + if (!node || node == sceneRoot) return; + + if (selectedNode == node) { + selectedNode = nullptr; + } + + if (node->parent) { + node->parent->removeChild(node); + } else { + auto it = std::find(rootNodes.begin(), rootNodes.end(), node); + if (it != rootNodes.end()) { + rootNodes.erase(it); + } + } + + delete node; + } + + void clearScene() { + selectedNode = nullptr; + // Clear all objects from scene root + if (sceneRoot) { + for (auto child : sceneRoot->children) { + delete child; + } + sceneRoot->children.clear(); + } + } +} sceneManager; + +// Options and values to display/toggle from the UI +struct UISettings { + bool displayModels = false; + bool displayBackground = false; + bool animateLight = false; + float lightSpeed = 0.25f; + std::array frameTimes{}; + float frameTimeMin = 9999.0f, frameTimeMax = 0.0f; + float lightTimer = 0.0f; + bool showGrid = true; + float gridSize = 10.0f; + int gridDivisions = 10; +} uiSettings; + +// ---------------------------------------------------------------------------- +// ImGUI class +// ---------------------------------------------------------------------------- +class ImGUI { +private: + // Vulkan resources for rendering the UI + VkSampler sampler; + vks::Buffer vertexBuffer; + vks::Buffer indexBuffer; + int32_t vertexCount = 0; + int32_t indexCount = 0; + VkDeviceMemory fontMemory = VK_NULL_HANDLE; + VkImage fontImage = VK_NULL_HANDLE; + VkImageView fontView = VK_NULL_HANDLE; + VkPipelineCache pipelineCache; + VkPipelineLayout pipelineLayout; + VkPipeline pipeline; + VkDescriptorPool descriptorPool; + VkDescriptorSetLayout descriptorSetLayout; + VkDescriptorSet descriptorSet; + vks::VulkanDevice *device; + VkPhysicalDeviceDriverProperties driverProperties = {}; + VulkanExampleBase *example; + ImGuiStyle vulkanStyle; + int selectedStyle = 0; +public: + // UI params are set via push constants + struct PushConstBlock { + glm::vec2 scale; + glm::vec2 translate; + } pushConstBlock; + + ImGUI(VulkanExampleBase *example) : example(example) + { + device = example->vulkanDevice; + ImGui::CreateContext(); + + //SRS - Set ImGui font and style scale factors to handle retina and other HiDPI displays + ImGuiIO& io = ImGui::GetIO(); + io.FontGlobalScale = example->ui.scale; + ImGuiStyle& style = ImGui::GetStyle(); + style.ScaleAllSizes(example->ui.scale); + }; + + ~ImGUI() + { + ImGui::DestroyContext(); + // Release all Vulkan resources required for rendering imGui + vertexBuffer.destroy(); + indexBuffer.destroy(); + vkDestroyImage(device->logicalDevice, fontImage, nullptr); + vkDestroyImageView(device->logicalDevice, fontView, nullptr); + vkFreeMemory(device->logicalDevice, fontMemory, nullptr); + vkDestroySampler(device->logicalDevice, sampler, nullptr); + vkDestroyPipelineCache(device->logicalDevice, pipelineCache, nullptr); + vkDestroyPipeline(device->logicalDevice, pipeline, nullptr); + vkDestroyPipelineLayout(device->logicalDevice, pipelineLayout, nullptr); + vkDestroyDescriptorPool(device->logicalDevice, descriptorPool, nullptr); + vkDestroyDescriptorSetLayout(device->logicalDevice, descriptorSetLayout, nullptr); + } + + // Initialize styles, keys, etc. + void init(float width, float height) + { + // Color scheme + vulkanStyle = ImGui::GetStyle(); + vulkanStyle.Colors[ImGuiCol_TitleBg] = ImVec4(1.0f, 0.0f, 0.0f, 0.6f); + vulkanStyle.Colors[ImGuiCol_TitleBgActive] = ImVec4(1.0f, 0.0f, 0.0f, 0.8f); + vulkanStyle.Colors[ImGuiCol_MenuBarBg] = ImVec4(1.0f, 0.0f, 0.0f, 0.4f); + vulkanStyle.Colors[ImGuiCol_Header] = ImVec4(1.0f, 0.0f, 0.0f, 0.4f); + vulkanStyle.Colors[ImGuiCol_CheckMark] = ImVec4(0.0f, 1.0f, 0.0f, 1.0f); + + setStyle(0); + + // Dimensions + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2(width, height); + io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f); +#if defined(_WIN32) + // If we directly work with os specific key codes, we need to map special key types like tab + io.KeyMap[ImGuiKey_Tab] = VK_TAB; + io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = VK_UP; + io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; + io.KeyMap[ImGuiKey_Backspace] = VK_BACK; + io.KeyMap[ImGuiKey_Enter] = VK_RETURN; + io.KeyMap[ImGuiKey_Space] = VK_SPACE; + io.KeyMap[ImGuiKey_Delete] = VK_DELETE; +#endif + } + + void setStyle(uint32_t index) + { + switch (index) + { + case 0: + { + ImGuiStyle& style = ImGui::GetStyle(); + style = vulkanStyle; + break; + } + case 1: + ImGui::StyleColorsClassic(); + break; + case 2: + ImGui::StyleColorsDark(); + break; + case 3: + ImGui::StyleColorsLight(); + break; + case 4: // Blue theme + { + ImGuiStyle& style = ImGui::GetStyle(); + style = ImGui::GetStyle(); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.0f, 0.3f, 0.8f, 0.6f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.0f, 0.4f, 1.0f, 0.8f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.0f, 0.2f, 0.6f, 0.4f); + style.Colors[ImGuiCol_Header] = ImVec4(0.0f, 0.3f, 0.7f, 0.4f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(0.0f, 1.0f, 1.0f, 1.0f); + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.05f, 0.05f, 0.15f, 0.9f); + break; + } + case 5: // Green theme + { + ImGuiStyle& style = ImGui::GetStyle(); + style = ImGui::GetStyle(); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.0f, 0.6f, 0.2f, 0.6f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.0f, 0.8f, 0.3f, 0.8f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.0f, 0.4f, 0.1f, 0.4f); + style.Colors[ImGuiCol_Header] = ImVec4(0.0f, 0.5f, 0.2f, 0.4f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(0.0f, 1.0f, 0.0f, 1.0f); + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.05f, 0.15f, 0.05f, 0.9f); + break; + } + case 6: // Purple theme + { + ImGuiStyle& style = ImGui::GetStyle(); + style = ImGui::GetStyle(); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.5f, 0.0f, 0.8f, 0.6f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.7f, 0.0f, 1.0f, 0.8f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.3f, 0.0f, 0.6f, 0.4f); + style.Colors[ImGuiCol_Header] = ImVec4(0.4f, 0.0f, 0.7f, 0.4f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(1.0f, 0.0f, 1.0f, 1.0f); + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.1f, 0.05f, 0.15f, 0.9f); + break; + } + } + } + + // Initialize all Vulkan resources used by the ui + void initResources(VkRenderPass renderPass, VkQueue copyQueue, const std::string& shadersPath) + { + ImGuiIO& io = ImGui::GetIO(); + + // Create font texture + unsigned char* fontData; + int texWidth, texHeight; + io.Fonts->GetTexDataAsRGBA32(&fontData, &texWidth, &texHeight); + VkDeviceSize uploadSize = texWidth*texHeight * 4 * sizeof(char); + + //SRS - Get Vulkan device driver information if available, use later for display + if (device->extensionSupported(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) + { + VkPhysicalDeviceProperties2 deviceProperties2 = {}; + deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + deviceProperties2.pNext = &driverProperties; + driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; + vkGetPhysicalDeviceProperties2(device->physicalDevice, &deviceProperties2); + } + + // Create target image for copy + VkImageCreateInfo imageInfo = vks::initializers::imageCreateInfo(); + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM; + imageInfo.extent.width = texWidth; + imageInfo.extent.height = texHeight; + imageInfo.extent.depth = 1; + imageInfo.mipLevels = 1; + imageInfo.arrayLayers = 1; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VK_CHECK_RESULT(vkCreateImage(device->logicalDevice, &imageInfo, nullptr, &fontImage)); + VkMemoryRequirements memReqs; + vkGetImageMemoryRequirements(device->logicalDevice, fontImage, &memReqs); + VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); + memAllocInfo.allocationSize = memReqs.size; + memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device->logicalDevice, &memAllocInfo, nullptr, &fontMemory)); + VK_CHECK_RESULT(vkBindImageMemory(device->logicalDevice, fontImage, fontMemory, 0)); + + // Image view + VkImageViewCreateInfo viewInfo = vks::initializers::imageViewCreateInfo(); + viewInfo.image = fontImage; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.format = VK_FORMAT_R8G8B8A8_UNORM; + viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.subresourceRange.levelCount = 1; + viewInfo.subresourceRange.layerCount = 1; + VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewInfo, nullptr, &fontView)); + + // Staging buffers for font data upload + vks::Buffer stagingBuffer; + + VK_CHECK_RESULT(device->createBuffer( + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &stagingBuffer, + uploadSize)); + + stagingBuffer.map(); + memcpy(stagingBuffer.mapped, fontData, uploadSize); + stagingBuffer.unmap(); + + // Copy buffer data to font image + VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + + // Prepare for transfer + vks::tools::setImageLayout( + copyCmd, + fontImage, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_HOST_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT); + + // Copy + VkBufferImageCopy bufferCopyRegion = {}; + bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + bufferCopyRegion.imageSubresource.layerCount = 1; + bufferCopyRegion.imageExtent.width = texWidth; + bufferCopyRegion.imageExtent.height = texHeight; + bufferCopyRegion.imageExtent.depth = 1; + + vkCmdCopyBufferToImage( + copyCmd, + stagingBuffer.buffer, + fontImage, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + &bufferCopyRegion + ); + + // Prepare for shader read + vks::tools::setImageLayout( + copyCmd, + fontImage, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + device->flushCommandBuffer(copyCmd, copyQueue, true); + + stagingBuffer.destroy(); + + // Font texture Sampler + VkSamplerCreateInfo samplerInfo = vks::initializers::samplerCreateInfo(); + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + VK_CHECK_RESULT(vkCreateSampler(device->logicalDevice, &samplerInfo, nullptr, &sampler)); + + // Descriptor pool + std::vector poolSizes = { + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) + }; + VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); + VK_CHECK_RESULT(vkCreateDescriptorPool(device->logicalDevice, &descriptorPoolInfo, nullptr, &descriptorPool)); + + // Descriptor set layout + std::vector setLayoutBindings = { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), + }; + VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device->logicalDevice, &descriptorLayout, nullptr, &descriptorSetLayout)); + + // Descriptor set + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device->logicalDevice, &allocInfo, &descriptorSet)); + VkDescriptorImageInfo fontDescriptor = vks::initializers::descriptorImageInfo( + sampler, + fontView, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + ); + std::vector writeDescriptorSets = { + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &fontDescriptor) + }; + vkUpdateDescriptorSets(device->logicalDevice, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); + + // Pipeline cache + VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {}; + pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + VK_CHECK_RESULT(vkCreatePipelineCache(device->logicalDevice, &pipelineCacheCreateInfo, nullptr, &pipelineCache)); + + // Pipeline layout + // Push constants for UI rendering parameters + VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0); + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); + pipelineLayoutCreateInfo.pushConstantRangeCount = 1; + pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; + VK_CHECK_RESULT(vkCreatePipelineLayout(device->logicalDevice, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + + // Setup graphics pipeline for UI rendering + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = + vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + + VkPipelineRasterizationStateCreateInfo rasterizationState = + vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); + + // Enable blending + VkPipelineColorBlendAttachmentState blendAttachmentState{}; + blendAttachmentState.blendEnable = VK_TRUE; + blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; + blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; + + VkPipelineColorBlendStateCreateInfo colorBlendState = + vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + + VkPipelineDepthStencilStateCreateInfo depthStencilState = + vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); + + VkPipelineViewportStateCreateInfo viewportState = + vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); + + VkPipelineMultisampleStateCreateInfo multisampleState = + vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + + std::vector dynamicStateEnables = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + VkPipelineDynamicStateCreateInfo dynamicState = + vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); + + std::array shaderStages{}; + + VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); + + pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; + pipelineCreateInfo.pRasterizationState = &rasterizationState; + pipelineCreateInfo.pColorBlendState = &colorBlendState; + pipelineCreateInfo.pMultisampleState = &multisampleState; + pipelineCreateInfo.pViewportState = &viewportState; + pipelineCreateInfo.pDepthStencilState = &depthStencilState; + pipelineCreateInfo.pDynamicState = &dynamicState; + pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); + pipelineCreateInfo.pStages = shaderStages.data(); + + // Vertex bindings an attributes based on ImGui vertex definition + std::vector vertexInputBindings = { + vks::initializers::vertexInputBindingDescription(0, sizeof(ImDrawVert), VK_VERTEX_INPUT_RATE_VERTEX), + }; + std::vector vertexInputAttributes = { + vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(ImDrawVert, pos)), // Location 0: Position + vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(ImDrawVert, uv)), // Location 1: UV + vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R8G8B8A8_UNORM, offsetof(ImDrawVert, col)), // Location 0: Color + }; + VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); + vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); + vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); + vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); + vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); + + pipelineCreateInfo.pVertexInputState = &vertexInputState; + + shaderStages[0] = example->loadShader(shadersPath + "imgui/ui.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = example->loadShader(shadersPath + "imgui/ui.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device->logicalDevice, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); + } + + // Recursive function to render Maya-style outliner nodes + void renderSceneNodeInOutliner(SceneNode* node, int depth = 0) { + if (!node) return; + + // Get type-specific icon + const char* icon = "📁"; // Default folder + switch (node->type) { + case SceneNode::PROCEDURAL_OBJECT: + switch (node->proceduralShape ? node->proceduralShape->type : -1) { + case 0: icon = "📦"; break; // Cube + case 1: icon = "🔵"; break; // Sphere + case 2: icon = "🔴"; break; // Cylinder + case 3: icon = "📏"; break; // Plane + case 4: icon = "🔺"; break; // Cone + case 6: icon = "🍩"; break; // Torus + default: icon = "🔷"; break; // Generic shape + } + break; + case SceneNode::MODEL_OBJECT: icon = "🗿"; break; + case SceneNode::LIGHT_OBJECT: icon = "💡"; break; + case SceneNode::CAMERA_OBJECT: icon = "📷"; break; + case SceneNode::SCENE_ROOT: icon = "📁"; break; + } + + // Create unique ID for ImGui + ImGui::PushID(node); + + ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; + if (sceneManager.selectedNode == node) { + flags |= ImGuiTreeNodeFlags_Selected; + } + if (node->children.empty()) { + flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; + } + + // Visibility toggle + if (node->type != SceneNode::SCENE_ROOT) { + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + if (ImGui::SmallButton(node->visible ? "👁" : "🚫")) { + node->visible = !node->visible; + } + ImGui::PopStyleColor(); + ImGui::SameLine(); + } + + // Node name with icon + bool nodeOpen = false; + if (node->children.empty()) { + // Leaf node - use Selectable + flags &= ~ImGuiTreeNodeFlags_OpenOnArrow; // Remove arrow for leaf nodes + bool isSelected = (sceneManager.selectedNode == node); + if (ImGui::Selectable((std::string(icon) + " " + node->name).c_str(), isSelected)) { + sceneManager.selectedNode = node; + } + } else { + // Branch node - use TreeNode + nodeOpen = ImGui::TreeNodeEx((std::string(icon) + " " + node->name).c_str(), flags); + if (ImGui::IsItemClicked()) { + sceneManager.selectedNode = node; + } + } + + // Context menu + if (ImGui::BeginPopupContextItem()) { + if (node->type != SceneNode::SCENE_ROOT) { + if (ImGui::MenuItem("Delete", "Del")) { + sceneManager.deleteNode(node); + ImGui::PopID(); + ImGui::EndPopup(); + return; // Node deleted, exit + } + if (ImGui::MenuItem("Duplicate", "Ctrl+D")) { + // TODO: Implement duplication + } + ImGui::Separator(); + } + if (ImGui::MenuItem("Create Child")) { + // TODO: Show submenu for object types + } + ImGui::EndPopup(); + } + + // Render children if node is open + if (nodeOpen && !node->children.empty()) { + for (auto child : node->children) { + renderSceneNodeInOutliner(child, depth + 1); + } + ImGui::TreePop(); + } + + ImGui::PopID(); + } + + // Starts a new imGui frame and sets up windows and ui elements + void newFrame(VulkanExampleBase *example, bool updateFrameGraph) + { + ImGui::NewFrame(); + + // Menu Bar + if (ImGui::BeginMainMenuBar()) + { + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("New Scene", "Ctrl+N")) { + // Clear scene + sceneManager.clearScene(); + } + if (ImGui::MenuItem("Open Scene", "Ctrl+O")) { + // TODO: Implement scene loading + } + if (ImGui::MenuItem("Save Scene", "Ctrl+S")) { + // TODO: Implement scene saving + } + ImGui::Separator(); + if (ImGui::MenuItem("Exit", "Alt+F4")) { + example->prepared = false; + } + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Preferences")) + { + if (ImGui::BeginMenu("UI Theme")) + { + if (ImGui::MenuItem("Vulkan Red", nullptr, selectedStyle == 0)) { setStyle(0); selectedStyle = 0; } + if (ImGui::MenuItem("Classic", nullptr, selectedStyle == 1)) { setStyle(1); selectedStyle = 1; } + if (ImGui::MenuItem("Dark", nullptr, selectedStyle == 2)) { setStyle(2); selectedStyle = 2; } + if (ImGui::MenuItem("Light", nullptr, selectedStyle == 3)) { setStyle(3); selectedStyle = 3; } + if (ImGui::MenuItem("Blue", nullptr, selectedStyle == 4)) { setStyle(4); selectedStyle = 4; } + if (ImGui::MenuItem("Green", nullptr, selectedStyle == 5)) { setStyle(5); selectedStyle = 5; } + if (ImGui::MenuItem("Purple", nullptr, selectedStyle == 6)) { setStyle(6); selectedStyle = 6; } + ImGui::EndMenu(); + } + ImGui::Separator(); + if (ImGui::BeginMenu("Viewport")) + { + ImGui::MenuItem("Show Grid", nullptr, &uiSettings.showGrid); + ImGui::EndMenu(); + } + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Help")) + { + if (ImGui::MenuItem("About")) { + // TODO: Show about dialog + } + ImGui::EndMenu(); + } + ImGui::EndMainMenuBar(); + } + + // Init imGui windows and elements + + // Debug window + ImGui::SetWindowPos(ImVec2(20 * example->ui.scale, 20 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetWindowSize(ImVec2(300 * example->ui.scale, 300 * example->ui.scale), ImGuiSetCond_Always); + ImGui::TextUnformatted(example->title.c_str()); + ImGui::TextUnformatted(device->properties.deviceName); + + //SRS - Display Vulkan API version and device driver information if available (otherwise blank) + ImGui::Text("Vulkan API %i.%i.%i", VK_API_VERSION_MAJOR(device->properties.apiVersion), VK_API_VERSION_MINOR(device->properties.apiVersion), VK_API_VERSION_PATCH(device->properties.apiVersion)); + ImGui::Text("%s %s", driverProperties.driverName, driverProperties.driverInfo); + + // Update frame time display + if (updateFrameGraph) { + std::rotate(uiSettings.frameTimes.begin(), uiSettings.frameTimes.begin() + 1, uiSettings.frameTimes.end()); + float frameTime = 1000.0f / (example->frameTimer * 1000.0f); + uiSettings.frameTimes.back() = frameTime; + if (frameTime < uiSettings.frameTimeMin) { + uiSettings.frameTimeMin = frameTime; + } + if (frameTime > uiSettings.frameTimeMax) { + uiSettings.frameTimeMax = frameTime; + } + } + + ImGui::PlotLines("Frame Times", &uiSettings.frameTimes[0], 50, 0, "", uiSettings.frameTimeMin, uiSettings.frameTimeMax, ImVec2(0, 80)); + + ImGui::Text("Camera"); + ImGui::InputFloat3("position", &example->camera.position.x, 2); + ImGui::InputFloat3("rotation", &example->camera.rotation.x, 2); + + + // Maya-Style Scene Hierarchy Panel + ImGui::SetNextWindowPos(ImVec2(20 * example->ui.scale, 360 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(300 * example->ui.scale, 400 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Scene Hierarchy"); + + // Header with object count + ImGui::Text("Scene Objects: %d", sceneManager.getObjectCount()); + ImGui::Separator(); + + // Render the hierarchical scene tree + if (sceneManager.sceneRoot) { + for (auto rootNode : sceneManager.rootNodes) { + renderSceneNodeInOutliner(rootNode); + } + } + + // Show message if scene is empty + if (sceneManager.getObjectCount() == 0) { + ImGui::Spacing(); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Scene is empty"); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Add objects from Asset Browser"); + } + + ImGui::End(); + + // Inspector Panel + ImGui::SetNextWindowPos(ImVec2(1180 * example->ui.scale, 20 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(300 * example->ui.scale, 700 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Inspector"); + ImGui::Text("Object Properties:"); + ImGui::Separator(); + + if (sceneManager.selectedNode && sceneManager.selectedNode->type != SceneNode::SCENE_ROOT) { + SceneNode* selectedNode = sceneManager.selectedNode; + ImGui::Text("Selected: %s", selectedNode->name.c_str()); + ImGui::Separator(); + + // Object type info + const char* typeStr = "Unknown"; + switch (selectedNode->type) { + case SceneNode::PROCEDURAL_OBJECT: typeStr = "Procedural Object"; break; + case SceneNode::MODEL_OBJECT: typeStr = "3D Model"; break; + case SceneNode::LIGHT_OBJECT: typeStr = "Light"; break; + case SceneNode::CAMERA_OBJECT: typeStr = "Camera"; break; + } + ImGui::Text("Type: %s", typeStr); + ImGui::Separator(); + + // Transform controls + ImGui::Text("Transform:"); + bool transformChanged = false; + transformChanged |= ImGui::DragFloat3("Position", &selectedNode->position.x, 0.1f); + transformChanged |= ImGui::DragFloat3("Rotation", &selectedNode->rotation.x, 1.0f); + transformChanged |= ImGui::DragFloat3("Scale", &selectedNode->scale.x, 0.01f); + if (transformChanged) { + selectedNode->updateMatrix(); + } + ImGui::Separator(); + + // Procedural shape parameters + if (selectedNode->isProceduralShape && selectedNode->proceduralShape) { + ImGui::Text("Shape Parameters:"); + ProceduralShape* shape = selectedNode->proceduralShape; + bool regenerate = false; + + switch (shape->type) { + case 0: // Cube + regenerate |= ImGui::DragFloat("Width", &shape->params.width, 0.1f, 0.1f, 10.0f); + regenerate |= ImGui::DragFloat("Height", &shape->params.height, 0.1f, 0.1f, 10.0f); + regenerate |= ImGui::DragFloat("Depth", &shape->params.depth, 0.1f, 0.1f, 10.0f); + if (regenerate) { + *shape = ProceduralGeometry::generateCube(shape->params.width, shape->params.height, shape->params.depth); + } + break; + case 1: // Sphere + regenerate |= ImGui::DragFloat("Radius", &shape->params.radius, 0.1f, 0.1f, 5.0f); + regenerate |= ImGui::DragInt("Segments", &shape->params.segments, 1, 4, 64); + if (regenerate) { + *shape = ProceduralGeometry::generateSphere(shape->params.radius, shape->params.segments); + } + break; + case 3: // Plane + regenerate |= ImGui::DragFloat("Width", &shape->params.width, 0.1f, 0.1f, 10.0f); + regenerate |= ImGui::DragFloat("Height", &shape->params.height, 0.1f, 0.1f, 10.0f); + regenerate |= ImGui::DragInt("Subdivisions", &shape->params.subdivisions, 1, 1, 32); + if (regenerate) { + *shape = ProceduralGeometry::generatePlane(shape->params.width, shape->params.height, shape->params.subdivisions); + } + break; + case 4: // Cone + regenerate |= ImGui::DragFloat("Radius", &shape->params.radius, 0.1f, 0.1f, 5.0f); + regenerate |= ImGui::DragFloat("Height", &shape->params.height, 0.1f, 0.1f, 10.0f); + regenerate |= ImGui::DragInt("Segments", &shape->params.segments, 1, 3, 64); + if (regenerate) { + *shape = ProceduralGeometry::generateCone(shape->params.radius, shape->params.height, shape->params.segments); + } + break; + case 5: // Cylinder + regenerate |= ImGui::DragFloat("Radius", &shape->params.radius, 0.1f, 0.1f, 5.0f); + regenerate |= ImGui::DragFloat("Height", &shape->params.height, 0.1f, 0.1f, 10.0f); + regenerate |= ImGui::DragInt("Segments", &shape->params.segments, 1, 3, 64); + if (regenerate) { + *shape = ProceduralGeometry::generateCylinder(shape->params.radius, shape->params.height, shape->params.segments); + } + break; + case 6: // Torus + regenerate |= ImGui::DragFloat("Major Radius", &shape->params.majorRadius, 0.1f, 0.1f, 5.0f); + regenerate |= ImGui::DragFloat("Minor Radius", &shape->params.minorRadius, 0.1f, 0.05f, 2.0f); + regenerate |= ImGui::DragInt("Major Segments", &shape->params.segments, 1, 3, 64); + regenerate |= ImGui::DragInt("Minor Segments", &shape->params.subdivisions, 1, 3, 32); + if (regenerate) { + *shape = ProceduralGeometry::generateTorus(shape->params.majorRadius, shape->params.minorRadius, shape->params.segments, shape->params.subdivisions); + } + break; + } + ImGui::Separator(); + } + } else { + ImGui::Text("Selected: None"); + ImGui::Text("Select an object in the Scene Hierarchy"); + ImGui::Separator(); + } + + // Lighting Settings + ImGui::Text("Lighting:"); + ImGui::Checkbox("Animate light", &uiSettings.animateLight); + ImGui::SliderFloat("Light speed", &uiSettings.lightSpeed, 0.1f, 1.0f); + ImGui::Separator(); + + // Grid Settings + ImGui::Text("Viewport Grid:"); + ImGui::Checkbox("Show Grid", &uiSettings.showGrid); + if (uiSettings.showGrid) { + ImGui::DragFloat("Grid Size", &uiSettings.gridSize, 0.5f, 1.0f, 50.0f); + ImGui::DragInt("Grid Divisions", &uiSettings.gridDivisions, 1, 2, 50); + } + ImGui::Separator(); + + // Procedural generation settings + ImGui::Text("Procedural Settings:"); + ImGui::Separator(); + //ImGui::ShowStyleSelector("UI style"); + + if (ImGui::Combo("UI style", &selectedStyle, "Vulkan Red\0Classic\0Dark\0Light\0Blue\0Green\0Purple\0")) { + setStyle(selectedStyle); + } + + ImGui::End(); + + // Asset Browser Panel + ImGui::SetNextWindowPos(ImVec2(20 * example->ui.scale, 780 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(600 * example->ui.scale, 220 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Asset Browser"); + ImGui::Text("Project Assets:"); + ImGui::Separator(); + + if (ImGui::CollapsingHeader("Procedural Shapes", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Text("Basic Geometric Shapes:"); + ImGui::Separator(); + + // Create buttons for each shape type - First row + if (ImGui::Button("📦 Cube")) { + ProceduralShape cube = ProceduralGeometry::generateCube(); + sceneManager.addProceduralShape(cube); + ((VulkanExample*)example)->addShapeToRenderer(cube); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural cube to the scene"); + ImGui::SameLine(); + if (ImGui::Button("🔵 Sphere")) { + ProceduralShape sphere = ProceduralGeometry::generateSphere(); + sceneManager.addProceduralShape(sphere); + static_cast(example)->addShapeToRenderer(sphere); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural sphere to the scene"); + ImGui::SameLine(); + if (ImGui::Button("📏 Plane")) { + ProceduralShape plane = ProceduralGeometry::generatePlane(); + sceneManager.addProceduralShape(plane); + static_cast(example)->addShapeToRenderer(plane); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural plane to the scene"); + + // Second row + if (ImGui::Button("🔺 Cone")) { + ProceduralShape cone = ProceduralGeometry::generateCone(); + sceneManager.addProceduralShape(cone); + static_cast(example)->addShapeToRenderer(cone); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural cone to the scene"); + ImGui::SameLine(); + if (ImGui::Button("🔴 Cylinder")) { + ProceduralShape cylinder = ProceduralGeometry::generateCylinder(); + sceneManager.addProceduralShape(cylinder); + static_cast(example)->addShapeToRenderer(cylinder); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural cylinder to the scene"); + ImGui::SameLine(); + if (ImGui::Button("🍩 Torus")) { + ProceduralShape torus = ProceduralGeometry::generateTorus(); + sceneManager.addProceduralShape(torus); + static_cast(example)->addShapeToRenderer(torus); + } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Add a procedural torus to the scene"); + } + + if (ImGui::CollapsingHeader("Models")) + { + ImGui::Text("• MobulaBirostris.gltf"); + ImGui::Text("• PolarBear.gltf"); + } + if (ImGui::CollapsingHeader("Textures")) + { + ImGui::Text("• Loading textures from glTF files..."); + } + if (ImGui::CollapsingHeader("Materials")) + { + ImGui::Text("• Default Vulkan Materials"); + } + ImGui::End(); + + // Console Panel + ImGui::SetNextWindowPos(ImVec2(640 * example->ui.scale, 780 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(840 * example->ui.scale, 200 * example->ui.scale), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Console"); + ImGui::Text("System Console:"); + ImGui::Separator(); + ImGui::Text("[INFO] ProceduralEngine - Vulkan Renderer initialized"); + ImGui::Text("[INFO] Scene loaded successfully - Ready for procedural generation"); + ImGui::Separator(); + static char inputBuf[256] = ""; + if (ImGui::InputText("Command", inputBuf, sizeof(inputBuf), ImGuiInputTextFlags_EnterReturnsTrue)) + { + // Process command + inputBuf[0] = '\0'; + } + ImGui::End(); + + //SRS - ShowDemoWindow() sets its own initial position and size, cannot override here + // ImGui::ShowDemoWindow(); + + // Render to generate draw buffers + ImGui::Render(); + } + + // Update vertex and index buffer containing the imGui elements when required + void updateBuffers() + { + ImDrawData* imDrawData = ImGui::GetDrawData(); + + // Note: Alignment is done inside buffer creation + VkDeviceSize vertexBufferSize = imDrawData->TotalVtxCount * sizeof(ImDrawVert); + VkDeviceSize indexBufferSize = imDrawData->TotalIdxCount * sizeof(ImDrawIdx); + + if ((vertexBufferSize == 0) || (indexBufferSize == 0)) { + return; + } + + // Update buffers only if vertex or index count has been changed compared to current buffer size + + // Vertex buffer + if ((vertexBuffer.buffer == VK_NULL_HANDLE) || (vertexCount != imDrawData->TotalVtxCount)) { + vertexBuffer.unmap(); + vertexBuffer.destroy(); + VK_CHECK_RESULT(device->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &vertexBuffer, vertexBufferSize)); + vertexCount = imDrawData->TotalVtxCount; + vertexBuffer.map(); + } + + // Index buffer + if ((indexBuffer.buffer == VK_NULL_HANDLE) || (indexCount < imDrawData->TotalIdxCount)) { + indexBuffer.unmap(); + indexBuffer.destroy(); + VK_CHECK_RESULT(device->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &indexBuffer, indexBufferSize)); + indexCount = imDrawData->TotalIdxCount; + indexBuffer.map(); + } + + // Upload data + ImDrawVert* vtxDst = (ImDrawVert*)vertexBuffer.mapped; + ImDrawIdx* idxDst = (ImDrawIdx*)indexBuffer.mapped; + + for (int n = 0; n < imDrawData->CmdListsCount; n++) { + const ImDrawList* cmd_list = imDrawData->CmdLists[n]; + memcpy(vtxDst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idxDst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + vtxDst += cmd_list->VtxBuffer.Size; + idxDst += cmd_list->IdxBuffer.Size; + } + + // Flush to make writes visible to GPU + vertexBuffer.flush(); + indexBuffer.flush(); + } + + // Draw current imGui frame into a command buffer + void drawFrame(VkCommandBuffer commandBuffer) + { + ImGuiIO& io = ImGui::GetIO(); + + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + + VkViewport viewport = vks::initializers::viewport(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y, 0.0f, 1.0f); + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + + // UI scale and translate via push constants + pushConstBlock.scale = glm::vec2(2.0f / io.DisplaySize.x, 2.0f / io.DisplaySize.y); + pushConstBlock.translate = glm::vec2(-1.0f); + vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock); + + // Render commands + ImDrawData* imDrawData = ImGui::GetDrawData(); + int32_t vertexOffset = 0; + int32_t indexOffset = 0; + + if (imDrawData->CmdListsCount > 0) { + + VkDeviceSize offsets[1] = { 0 }; + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer.buffer, offsets); + vkCmdBindIndexBuffer(commandBuffer, indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16); + + for (int32_t i = 0; i < imDrawData->CmdListsCount; i++) + { + const ImDrawList* cmd_list = imDrawData->CmdLists[i]; + for (int32_t j = 0; j < cmd_list->CmdBuffer.Size; j++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[j]; + VkRect2D scissorRect; + scissorRect.offset.x = std::max((int32_t)(pcmd->ClipRect.x), 0); + scissorRect.offset.y = std::max((int32_t)(pcmd->ClipRect.y), 0); + scissorRect.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissorRect.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y); + vkCmdSetScissor(commandBuffer, 0, 1, &scissorRect); + vkCmdDrawIndexed(commandBuffer, pcmd->ElemCount, 1, indexOffset, vertexOffset, 0); + indexOffset += pcmd->ElemCount; + } +#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && TARGET_OS_SIMULATOR + // Apple Device Simulator does not support vkCmdDrawIndexed() with vertexOffset > 0, so rebind vertex buffer instead + offsets[0] += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert); + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer.buffer, offsets); +#else + vertexOffset += cmd_list->VtxBuffer.Size; +#endif + } + } + } + +}; + +// ---------------------------------------------------------------------------- +// VulkanExample +// ---------------------------------------------------------------------------- + +class VulkanExample : public VulkanExampleBase +{ +public: + ImGUI *imGui = nullptr; + + struct Models { + vkglTF::Model models; + vkglTF::Model logos; + vkglTF::Model background; + } models; + + + vks::Buffer uniformBufferVS; + + struct UBOVS { + glm::mat4 projection; + glm::mat4 modelview; + glm::vec4 lightPos; + } uboVS; + + VkPipelineLayout pipelineLayout; + VkPipeline pipeline; + VkDescriptorSetLayout descriptorSetLayout; + VkDescriptorSet descriptorSet; + + VulkanExample() : VulkanExampleBase() + { + title = "ProceduralEngine - Vulkan 3D Viewport"; + camera.type = Camera::CameraType::lookat; + camera.setPosition(glm::vec3(0.0f, 0.0f, -8.0f)); + camera.setRotation(glm::vec3(4.5f, -380.0f, 0.0f)); + camera.setPerspective(45.0f, (float)width / (float)height, 0.1f, 256.0f); + + //SRS - Enable VK_KHR_get_physical_device_properties2 to retrieve device driver information for display + enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + + // Don't use the ImGui overlay of the base framework in this sample + settings.overlay = false; + } + + ~VulkanExample() + { + vkDestroyPipeline(device, pipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + + uniformBufferVS.destroy(); + proceduralRenderer.cleanup(device); + + delete imGui; + } + + void addShapeToRenderer(const ProceduralShape& shape) { + proceduralRenderer.addShape(shape, vulkanDevice, queue); + } + + void renderProceduralShapes(VkCommandBuffer commandBuffer) { + // Render all procedural shapes in the scene + uint32_t shapeIndex = 0; + renderSceneNodeShapes(sceneManager.sceneRoot, commandBuffer, shapeIndex); + } + + void renderSceneNodeShapes(SceneNode* node, VkCommandBuffer commandBuffer, uint32_t& shapeIndex) { + if (!node) return; + + // Render this node if it's a procedural shape and visible + if (node->type == SceneNode::PROCEDURAL_OBJECT && node->visible && node->isProceduralShape && node->proceduralShape) { + proceduralRenderer.draw(commandBuffer, shapeIndex); + shapeIndex++; + } + + // Recursively render children + for (auto child : node->children) { + renderSceneNodeShapes(child, commandBuffer, shapeIndex); + } + } + + void buildCommandBuffers() + { + VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); + + VkClearValue clearValues[2]; + clearValues[0].color = { { 0.2f, 0.2f, 0.2f, 1.0f} }; + clearValues[1].depthStencil = { 1.0f, 0 }; + + VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); + renderPassBeginInfo.renderPass = renderPass; + renderPassBeginInfo.renderArea.offset.x = 0; + renderPassBeginInfo.renderArea.offset.y = 0; + renderPassBeginInfo.renderArea.extent.width = width; + renderPassBeginInfo.renderArea.extent.height = height; + renderPassBeginInfo.clearValueCount = 2; + renderPassBeginInfo.pClearValues = clearValues; + + imGui->newFrame(this, (frameCounter == 0)); + imGui->updateBuffers(); + + for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) + { + // Set target frame buffer + renderPassBeginInfo.framebuffer = frameBuffers[i]; + + VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); + + vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); + vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); + + VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); + vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); + + // Render scene + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + + VkDeviceSize offsets[1] = { 0 }; + if (uiSettings.displayBackground) { + models.background.draw(drawCmdBuffers[i]); + } + + if (uiSettings.displayModels) { + models.models.draw(drawCmdBuffers[i]); + } + + // Render procedural shapes + renderProceduralShapes(drawCmdBuffers[i]); + + // Render imGui + if (ui.visible) { + imGui->drawFrame(drawCmdBuffers[i]); + } + + vkCmdEndRenderPass(drawCmdBuffers[i]); + + VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); + } + } + + void setupLayoutsAndDescriptors() + { + // descriptor pool + std::vector poolSizes = { + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) + }; + VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); + + // Set layout + std::vector setLayoutBindings = { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), + }; + VkDescriptorSetLayoutCreateInfo descriptorLayout = + vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); + + // Pipeline layout + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + + // Descriptor set + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); + std::vector writeDescriptorSets = { + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferVS.descriptor), + }; + vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); + } + + void preparePipelines() + { + // Rendering + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); + VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); + VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); + + std::array shaderStages; + + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); + pipelineCI.pInputAssemblyState = &inputAssemblyState; + pipelineCI.pRasterizationState = &rasterizationState; + pipelineCI.pColorBlendState = &colorBlendState; + pipelineCI.pMultisampleState = &multisampleState; + pipelineCI.pViewportState = &viewportState; + pipelineCI.pDepthStencilState = &depthStencilState; + pipelineCI.pDynamicState = &dynamicState; + pipelineCI.stageCount = static_cast(shaderStages.size()); + pipelineCI.pStages = shaderStages.data(); + pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color });; + + shaderStages[0] = loadShader(getShadersPath() + "imgui/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getShadersPath() + "imgui/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); + } + + // Prepare and initialize uniform buffer containing shader uniforms + void prepareUniformBuffers() + { + // Vertex shader uniform buffer block + VK_CHECK_RESULT(vulkanDevice->createBuffer( + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &uniformBufferVS, + sizeof(uboVS), + &uboVS)); + + updateUniformBuffers(); + } + + void updateUniformBuffers() + { + // Vertex shader + uboVS.projection = camera.matrices.perspective; + uboVS.modelview = camera.matrices.view * glm::mat4(1.0f); + + // Light source + if (uiSettings.animateLight) { + uiSettings.lightTimer += frameTimer * uiSettings.lightSpeed; + uboVS.lightPos.x = sin(glm::radians(uiSettings.lightTimer * 360.0f)) * 15.0f; + uboVS.lightPos.z = cos(glm::radians(uiSettings.lightTimer * 360.0f)) * 15.0f; + }; + + VK_CHECK_RESULT(uniformBufferVS.map()); + memcpy(uniformBufferVS.mapped, &uboVS, sizeof(uboVS)); + uniformBufferVS.unmap(); + } + + void draw() + { + VulkanExampleBase::prepareFrame(); + buildCommandBuffers(); + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; + VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + VulkanExampleBase::submitFrame(); + } + + void loadAssets() + { + const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; + // Models available in assets but not auto-loaded + // models.models.loadFromFile(getAssetPath() + "models/MobulaBirostris.gltf", vulkanDevice, queue, glTFLoadingFlags); + // models.background.loadFromFile(getAssetPath() + "models/PolarBear.gltf", vulkanDevice, queue, glTFLoadingFlags); + } + + void prepareImGui() + { + imGui = new ImGUI(this); + imGui->init((float)width, (float)height); + imGui->initResources(renderPass, queue, getShadersPath()); + } + + void prepare() + { + VulkanExampleBase::prepare(); + loadAssets(); + prepareUniformBuffers(); + setupLayoutsAndDescriptors(); + preparePipelines(); + prepareImGui(); + buildCommandBuffers(); + prepared = true; + } + + virtual void render() + { + if (!prepared) + return; + + updateUniformBuffers(); + + // Update imGui + ImGuiIO& io = ImGui::GetIO(); + + io.DisplaySize = ImVec2((float)width, (float)height); + io.DeltaTime = frameTimer; + + io.MousePos = ImVec2(mouseState.position.x, mouseState.position.y); + io.MouseDown[0] = mouseState.buttons.left && ui.visible; + io.MouseDown[1] = mouseState.buttons.right && ui.visible; + io.MouseDown[2] = mouseState.buttons.middle && ui.visible; + + draw(); + } + + virtual void mouseMoved(double x, double y, bool &handled) + { + ImGuiIO& io = ImGui::GetIO(); + handled = io.WantCaptureMouse && ui.visible; + } + +// Input handling is platform specific, to show how it's basically done this sample implements it for Windows +#if defined(_WIN32) + virtual void OnHandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + ImGuiIO& io = ImGui::GetIO(); + // Only react to keyboard input if ImGui is active + if (io.WantCaptureKeyboard) { + // Character input + if (uMsg == WM_CHAR) { + if (wParam > 0 && wParam < 0x10000) { + io.AddInputCharacter((unsigned short)wParam); + } + } + // Special keys (tab, cursor, etc.) + if ((wParam < 256) && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)) { + io.KeysDown[wParam] = true; + } + if ((wParam < 256) && (uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP)) { + io.KeysDown[wParam] = false; + } + } + } +#endif + +}; + +VULKAN_EXAMPLE_MAIN() diff --git a/examples/indirectdraw/README.md b/examples/indirectdraw/README.md deleted file mode 100644 index 3fdcd9af..00000000 --- a/examples/indirectdraw/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# Indirect drawing - - - -## Synopsis - -Issue multiple instanced draws for different meshes in one single draw call using indirect draw commands. - -## Requirements -If the [`multiDrawIndirect`](http://vulkan.gpuinfo.org/listreports.php?feature=multiDrawIndirect) feature is supported, only one draw call is issued for the plants. If this feature is not available multiple indirect draw commands are used. ***Note:*** When issuing many draw counts also make sure to stay within the limitations of [`maxDrawIndirectCount`](http://vulkan.gpuinfo.org/listreports.php?limit=maxDrawIndirectCount). - -## Description - -This example demonstrates the use of indirect draw commands. In addition to draw functions like [`vkCmdDraw`](https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkCmdDraw.html) and [`vkCmdDrawIndexed`](https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkCmdDrawIndexed.html), where the parameters that specify what is drawn are passed directly to the function ("direct drawing"), there also exist indirect drawing commands. - -[`vkCmdDrawIndirect`](https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkCmdDrawIndirect.html) and [`vkCmdDrawIndexedIndirect`](https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkCmdDrawIndexedIndirect.html) take the draw commands from a buffer object that contains descriptions on the draw commands to be issued, including instance and index counts, vertex offsets, etc. This also allows to draw multiple geometries with a single draw command as long as they're backed up by the same vertex (and index) buffer. - -This adds several new possibilities of generating (and updating) actual draw commands, as that buffer can be generated and updated offline with no need to actually update the command buffers that contain the actual drawing functions. - -Using indirect drawing you can generate the draw commands offline ahead of time on the CPU and even update them using shaders (as they're stored in a device local buffer). This adds lots of new possibilities to update draw commands without the CPU being involved, including GPU-based culling. - -The example generates a single indirect buffer that contains draw commands for 12 different plants at random position, scale and rotation also using instancing to render the objects multiple times. The whole foliage (and trees) seen in the screen are drawn using only one draw call. - -The different plant meshes are loaded from a single file and stored inside a single index and vertex buffer, index offsets are stored inside the indirect draw commands. - -For details on the use of instancing (and instanced vertex attributes), see the [instancing example](../instancing) - -## Points of interest - -### Preparing the indirect draw -The example generates the indirect drawing buffer right at the start. First step is to generate the data for the indirect draws. Vulkan has a dedicated struct for this called `VkDrawIndexedIndirectCommand` and the example uses a `std::vector` to store these before uploading them to the GPU: -```cpp -void prepareIndirectData() -{ - ... - uint32_t m = 0; - for (auto& meshDescriptor : meshes.plants.meshDescriptors) - { - VkDrawIndexedIndirectCommand indirectCmd{}; - indirectCmd.instanceCount = OBJECT_INSTANCE_COUNT; - indirectCmd.firstInstance = m * OBJECT_INSTANCE_COUNT; - indirectCmd.firstIndex = meshDescriptor.indexBase; - indirectCmd.indexCount = meshDescriptor.indexCount; - indirectCommands.push_back(indirectCmd); - m++; - } - ... -} -``` -The meshDescriptor is generated by the mesh loader and contains the index base and count of that mesh inside the global index buffer containing all plant meshes for the scenery. - -The indirect draw command for the second plant mesh looks like this: -```cpp -indirectCmd.indexCount = 1668; -indirectCmd.instanceCount = 2048; -indirectCmd.firstIndex = 960; -indirectCmd.vertexOffset = 0; -indirectCmd.firstInstance = 2048; -``` -Which will result in 2048 instances of the index data starting at index 960 (using 1668 indices) being drawn, the first instance is also important as the shader is using it for the instanced attributes of that object (position, rotation, scale). - -Once we have filled that vector we need to create the buffer that the GPU uses to read the indirect commands from: - -```cpp -VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &indirectCommandsBuffer, - stagingBuffer.size)); - -vulkanDevice->copyBuffer(&stagingBuffer, &indirectCommandsBuffer, queue); -``` -To use a buffer for indirect draw commands you need to specify the ```VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT``` usage flag at creation time. As the buffer is never again changed on the host side we stage it to the GPU to maximize performance. - -### Rendering -If the [`multiDrawIndirect`](http://vulkan.gpuinfo.org/listreports.php?feature=multiDrawIndirect) is supported, we can issue all indirect draws with one single draw call: -```cpp -void buildCommandBuffers() -{ - ... - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - vkCmdDrawIndexedIndirect(drawCmdBuffers[i], indirectCommandsBuffer.buffer, 0, indirectDrawCount, sizeof(VkDrawIndexedIndirectCommand)); - } -} -``` -We just pass the buffer handle to the buffer containing the indirect draw commands and the number of drawCounts. - -The non-indirect, non-instanced equivalent of this would be: -```cpp -for (auto indirectCmd : indirectCommands) - { - for (uint32_t j = 0; j < indirectCmd.instanceCount; j++) - { - vkCmdDrawIndexed(drawCmdBuffers[i], indirectCmd.indexCount, 1, indirectCmd.firstIndex, 0, indirectCmd.firstInstance + j); - } - } -``` - -If the GPU does not support ```multiDrawIndirect``` we have to issue the indirect draw commands one-by-one using a buffer offset instead: -```cpp -for (auto j = 0; j < indirectCommands.size(); j++) -{ - vkCmdDrawIndexedIndirect(drawCmdBuffers[i], indirectCommandsBuffer.buffer, j * sizeof(VkDrawIndexedIndirectCommand), 1, sizeof(VkDrawIndexedIndirectCommand)); -} -``` - -### Acknowledgments -- Plant and foliage models by [Hugues Muller](http://www.yughues-folio.com/) diff --git a/examples/indirectdraw/indirectdraw.cpp b/examples/indirectdraw/indirectdraw.cpp deleted file mode 100644 index ced8d3c7..00000000 --- a/examples/indirectdraw/indirectdraw.cpp +++ /dev/null @@ -1,483 +0,0 @@ -/* -* Vulkan Example - Indirect drawing -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -* -* Summary: -* Use a device local buffer that stores draw commands for instanced rendering of different meshes stored -* in the same buffer. -* -* Indirect drawing offloads draw command generation and offers the ability to update them on the GPU -* without the CPU having to touch the buffer again, also reducing the number of drawcalls. -* -* The example shows how to setup and fill such a buffer on the CPU side, stages it to the device and -* shows how to render it using only one draw command. -* -* See readme.md for details -* -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -// Number of instances per object -#if defined(__ANDROID__) -#define OBJECT_INSTANCE_COUNT 1024 -// Circular range of plant distribution -#define PLANT_RADIUS 20.0f -#else -#define OBJECT_INSTANCE_COUNT 2048 -// Circular range of plant distribution -#define PLANT_RADIUS 25.0f -#endif - -class VulkanExample : public VulkanExampleBase -{ -public: - struct { - vks::Texture2DArray plants; - vks::Texture2D ground; - } textures; - - struct { - vkglTF::Model plants; - vkglTF::Model ground; - vkglTF::Model skysphere; - } models; - - // Per-instance data block - struct InstanceData { - glm::vec3 pos; - glm::vec3 rot; - float scale; - uint32_t texIndex; - }; - - // Contains the instanced data - vks::Buffer instanceBuffer; - // Contains the indirect drawing commands - vks::Buffer indirectCommandsBuffer; - uint32_t indirectDrawCount{ 0 }; - - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - } uniformData; - vks::Buffer uniformBuffer; - - struct { - VkPipeline plants{ VK_NULL_HANDLE }; - VkPipeline ground{ VK_NULL_HANDLE }; - VkPipeline skysphere{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VkSampler samplerRepeat{ VK_NULL_HANDLE }; - - uint32_t objectCount = 0; - - // Store the indirect draw commands containing index offsets and instance count per object - std::vector indirectCommands; - - VulkanExample() : VulkanExampleBase() - { - title = "Indirect rendering"; - camera.type = Camera::CameraType::firstperson; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(-12.0f, 159.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.4f, 1.25f, 0.0f)); - camera.movementSpeed = 5.0f; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.plants, nullptr); - vkDestroyPipeline(device, pipelines.ground, nullptr); - vkDestroyPipeline(device, pipelines.skysphere, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - textures.plants.destroy(); - textures.ground.destroy(); - instanceBuffer.destroy(); - indirectCommandsBuffer.destroy(); - uniformBuffer.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Example uses multi draw indirect if available - if (deviceFeatures.multiDrawIndirect) { - enabledFeatures.multiDrawIndirect = VK_TRUE; - } - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - }; - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.18f, 0.27f, 0.5f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - // Skysphere - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skysphere); - models.skysphere.draw(drawCmdBuffers[i]); - // Ground - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.ground); - models.ground.draw(drawCmdBuffers[i]); - - // [POI] Instanced multi draw rendering of the plants - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.plants); - // Binding point 0 : Mesh vertex buffer - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &models.plants.vertices.buffer, offsets); - // Binding point 1 : Instance data buffer - vkCmdBindVertexBuffers(drawCmdBuffers[i], 1, 1, &instanceBuffer.buffer, offsets); - - vkCmdBindIndexBuffer(drawCmdBuffers[i], models.plants.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - - // If the multi draw feature is supported: - // One draw call for an arbitrary number of objects - // Index offsets and instance count are taken from the indirect buffer - if (vulkanDevice->features.multiDrawIndirect) - { - vkCmdDrawIndexedIndirect(drawCmdBuffers[i], indirectCommandsBuffer.buffer, 0, indirectDrawCount, sizeof(VkDrawIndexedIndirectCommand)); - } - else - { - // If multi draw is not available, we must issue separate draw commands - for (auto j = 0; j < indirectCommands.size(); j++) - { - vkCmdDrawIndexedIndirect(drawCmdBuffers[i], indirectCommandsBuffer.buffer, j * sizeof(VkDrawIndexedIndirectCommand), 1, sizeof(VkDrawIndexedIndirectCommand)); - } - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.plants.loadFromFile(getAssetPath() + "models/plants.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.ground.loadFromFile(getAssetPath() + "models/plane_circle.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.skysphere.loadFromFile(getAssetPath() + "models/sphere.gltf", vulkanDevice, queue, glTFLoadingFlags); - textures.plants.loadFromFile(getAssetPath() + "textures/texturearray_plants_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.ground.loadFromFile(getAssetPath() + "textures/ground_dry_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1: Fragment shader combined sampler (plants texture array) - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 1: Fragment shader combined sampler (ground texture) - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1: Plants texture array combined - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.plants.descriptor), - // Binding 2: Ground texture combined - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.ground.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - - // This example uses two different input states, one for the instanced part and one for non-instanced rendering - VkPipelineVertexInputStateCreateInfo inputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - std::vector bindingDescriptions; - std::vector attributeDescriptions; - - // Vertex input bindings - // The instancing pipeline uses a vertex input state with two bindings - bindingDescriptions = { - // Binding point 0: Mesh vertex layout description at per-vertex rate - vks::initializers::vertexInputBindingDescription(0, sizeof(vkglTF::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - // Binding point 1: Instanced data at per-instance rate - vks::initializers::vertexInputBindingDescription(1, sizeof(InstanceData), VK_VERTEX_INPUT_RATE_INSTANCE) - }; - - // Vertex attribute bindings - // Note that the shader declaration for per-vertex and per-instance attributes is the same, the different input rates are only stored in the bindings: - // instanced.vert: - // layout (location = 0) in vec3 inPos; Per-Vertex - // ... - // layout (location = 4) in vec3 instancePos; Per-Instance - attributeDescriptions = { - // Per-vertex attributes - // These are advanced for each vertex fetched by the vertex shader - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Location 0: Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Location 1: Normal - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32_SFLOAT, sizeof(float) * 6), // Location 2: Texture coordinates - vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 8), // Location 3: Color - // Per-Instance attributes - // These are fetched for each instance rendered - vks::initializers::vertexInputAttributeDescription(1, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(InstanceData, pos)), // Location 4: Position - vks::initializers::vertexInputAttributeDescription(1, 5, VK_FORMAT_R32G32B32_SFLOAT, offsetof(InstanceData, rot)), // Location 5: Rotation - vks::initializers::vertexInputAttributeDescription(1, 6, VK_FORMAT_R32_SFLOAT, offsetof(InstanceData, scale)), // Location 6: Scale - vks::initializers::vertexInputAttributeDescription(1, 7, VK_FORMAT_R32_SINT, offsetof(InstanceData, texIndex)), // Location 7: Texture array layer index - }; - inputState.pVertexBindingDescriptions = bindingDescriptions.data(); - inputState.pVertexAttributeDescriptions = attributeDescriptions.data(); - inputState.vertexBindingDescriptionCount = static_cast(bindingDescriptions.size()); - inputState.vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size()); - - pipelineCreateInfo.pVertexInputState = &inputState; - - // Indirect (and instanced) pipeline for the plants - shaderStages[0] = loadShader(getShadersPath() + "indirectdraw/indirectdraw.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "indirectdraw/indirectdraw.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.plants)); - - // Only use non-instanced vertex attributes for models rendered without instancing - inputState.vertexBindingDescriptionCount = 1; - inputState.vertexAttributeDescriptionCount = 4; - - // Ground - shaderStages[0] = loadShader(getShadersPath() + "indirectdraw/ground.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "indirectdraw/ground.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.ground)); - - // Skysphere - shaderStages[0] = loadShader(getShadersPath() + "indirectdraw/skysphere.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "indirectdraw/skysphere.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - depthStencilState.depthWriteEnable = VK_FALSE; - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.skysphere)); - } - - // Prepare (and stage) a buffer containing the indirect draw commands - void prepareIndirectData() - { - indirectCommands.clear(); - - // Create on indirect command for node in the scene with a mesh attached to it - uint32_t m = 0; - for (auto &node : models.plants.nodes) - { - if (node->mesh) - { - VkDrawIndexedIndirectCommand indirectCmd{}; - indirectCmd.instanceCount = OBJECT_INSTANCE_COUNT; - indirectCmd.firstInstance = m * OBJECT_INSTANCE_COUNT; - // A glTF node may consist of multiple primitives, but for this saample we only care for the first primitive - indirectCmd.firstIndex = node->mesh->primitives[0]->firstIndex; - indirectCmd.indexCount = node->mesh->primitives[0]->indexCount; - - indirectCommands.push_back(indirectCmd); - - m++; - } - } - - indirectDrawCount = static_cast(indirectCommands.size()); - - objectCount = 0; - for (auto indirectCmd : indirectCommands) - { - objectCount += indirectCmd.instanceCount; - } - - vks::Buffer stagingBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - indirectCommands.size() * sizeof(VkDrawIndexedIndirectCommand), - indirectCommands.data())); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &indirectCommandsBuffer, - stagingBuffer.size)); - - vulkanDevice->copyBuffer(&stagingBuffer, &indirectCommandsBuffer, queue); - - stagingBuffer.destroy(); - } - - // Prepare (and stage) a buffer containing instanced data for the mesh draws - void prepareInstanceData() - { - std::vector instanceData; - instanceData.resize(objectCount); - - std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::uniform_real_distribution uniformDist(0.0f, 1.0f); - - for (uint32_t i = 0; i < objectCount; i++) { - float theta = 2 * float(M_PI) * uniformDist(rndEngine); - float phi = acos(1 - 2 * uniformDist(rndEngine)); - instanceData[i].rot = glm::vec3(0.0f, float(M_PI) * uniformDist(rndEngine), 0.0f); - instanceData[i].pos = glm::vec3(sin(phi) * cos(theta), 0.0f, cos(phi)) * PLANT_RADIUS; - instanceData[i].scale = 1.0f + uniformDist(rndEngine) * 2.0f; - instanceData[i].texIndex = i / OBJECT_INSTANCE_COUNT; - } - - vks::Buffer stagingBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - instanceData.size() * sizeof(InstanceData), - instanceData.data())); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &instanceBuffer, - stagingBuffer.size)); - - vulkanDevice->copyBuffer(&stagingBuffer, &instanceBuffer, queue); - - stagingBuffer.destroy(); - } - - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(uniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffer() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareIndirectData(); - prepareInstanceData(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) { - return; - } - updateUniformBuffer(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (!vulkanDevice->features.multiDrawIndirect) { - if (overlay->header("Info")) { - overlay->text("multiDrawIndirect not supported"); - } - } - if (overlay->header("Statistics")) { - overlay->text("Objects: %d", objectCount); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/inlineuniformblocks/inlineuniformblocks.cpp b/examples/inlineuniformblocks/inlineuniformblocks.cpp deleted file mode 100644 index 8d79a908..00000000 --- a/examples/inlineuniformblocks/inlineuniformblocks.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* -* Vulkan Example - Using inline uniform blocks for passing data to shader stages at descriptor setup - -* Note: Requires a device that supports the VK_EXT_inline_uniform_block extension -* -* Relevant code parts are marked with [POI] -* -* Copyright (C) 2018-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - VkPhysicalDeviceInlineUniformBlockFeaturesEXT enabledInlineUniformBlockFeatures{}; - - vkglTF::Model model; - - struct Object { - struct Material { - float roughness; - float metallic; - float r, g, b; - float ambient; - } material; - VkDescriptorSet descriptorSet; - void setRandomMaterial(bool applyRandomSeed) { - std::random_device rndDevice; - std::default_random_engine rndEngine(applyRandomSeed ? rndDevice() : 0); - std::uniform_real_distribution rndDist(0.1f, 1.0f); - material.r = rndDist(rndEngine); - material.g = rndDist(rndEngine); - material.b = rndDist(rndEngine); - material.ambient = 0.0025f; - material.roughness = glm::clamp(rndDist(rndEngine), 0.005f, 1.0f); - material.metallic = glm::clamp(rndDist(rndEngine), 0.005f, 1.0f); - } - }; - std::array objects{}; - - struct UniformData { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - glm::vec3 camPos; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - struct DescriptorSetLaysts { - VkDescriptorSetLayout scene{ VK_NULL_HANDLE }; - VkDescriptorSetLayout object{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - VulkanExample() : VulkanExampleBase() - { - title = "Inline uniform blocks"; - camera.type = Camera::CameraType::firstperson; - camera.setPosition(glm::vec3(0.0f, 0.0f, -10.0f)); - camera.setRotation(glm::vec3(0.0, 0.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - camera.movementSpeed = 4.0f; - camera.rotationSpeed = 0.25f; - - /* - [POI] Enable extensions required for inline uniform blocks - */ - enabledDeviceExtensions.push_back(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - - /* - [POI] We also need to enable the inline uniform block feature (using the dedicated physical device structure) - */ - enabledInlineUniformBlockFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT; - enabledInlineUniformBlockFeatures.inlineUniformBlock = VK_TRUE; - deviceCreatepNextChain = &enabledInlineUniformBlockFeatures; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.scene, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.object, nullptr); - uniformBuffer.destroy(); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.15f, 0.15f, 0.15f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Render objects - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - uint32_t objcount = static_cast(objects.size()); - for (uint32_t x = 0; x < objcount; x++) { - /* - [POI] Bind descriptor sets - Set 0 = Scene matrices: - Set 1 = Object inline uniform block (In shader pbr.frag: layout (set = 1, binding = 0) uniform UniformInline ... ) - */ - std::vector descriptorSets = { - descriptorSet, - objects[x].descriptorSet - }; - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, descriptorSets.data(), 0, nullptr); - - glm::vec3 pos = glm::vec3(sin(glm::radians(x * (360.0f / objcount))), cos(glm::radians(x * (360.0f / objcount))), 0.0f) * 3.5f; - - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::vec3), &pos); - model.draw(drawCmdBuffers[i]); - } - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - model.loadFromFile(getAssetPath() + "models/sphere.gltf", vulkanDevice, queue); - - // Setup random materials for every object in the scene - for (uint32_t i = 0; i < objects.size(); i++) { - objects[i].setRandomMaterial(!benchmark.active); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - /* [POI] Allocate inline uniform blocks */ - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, static_cast(objects.size()) * sizeof(Object::Material)), - }; - VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, static_cast(objects.size()) + 1); - /* - [POI] New structure that has to be chained into the descriptor pool's createinfo if you want to allocate inline uniform blocks - */ - VkDescriptorPoolInlineUniformBlockCreateInfoEXT descriptorPoolInlineUniformBlockCreateInfo{}; - descriptorPoolInlineUniformBlockCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT; - descriptorPoolInlineUniformBlockCreateInfo.maxInlineUniformBlockBindings = static_cast(objects.size()); - descriptorPoolCI.pNext = &descriptorPoolInlineUniformBlockCreateInfo; - - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorPool)); - - // Layouts - std::vector setLayoutBindings{}; - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI{}; - // Scene matrices - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - }; - descriptorLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayouts.scene)); - setLayoutBindings = { - /* - [POI] Setup inline uniform block for set 1 at binding 0 (see fragment shader) - Descriptor count for an inline uniform block contains data sizes of the block (last parameter) - */ - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(Object::Material)), - }; - descriptorLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayouts.object)); - - // Sets - // Scene - VkDescriptorSetAllocateInfo descriptorAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.scene, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocateInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - // Objects - for (auto& object : objects) { - VkDescriptorSetAllocateInfo descriptorAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.object, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocateInfo, &object.descriptorSet)); - - /* - [POI] New structure that defines size and data of the inline uniform block needs to be chained into the write descriptor set - We will be using this inline uniform block to pass per-object material information to the fragment shader - */ - VkWriteDescriptorSetInlineUniformBlockEXT writeDescriptorSetInlineUniformBlock{}; - writeDescriptorSetInlineUniformBlock.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT; - writeDescriptorSetInlineUniformBlock.dataSize = sizeof(Object::Material); - // Uniform data for the inline block - writeDescriptorSetInlineUniformBlock.pData = &object.material; - - /* - [POI] Setup the inline uniform block - */ - VkWriteDescriptorSet writeDescriptorSet{}; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; - writeDescriptorSet.dstSet = object.descriptorSet; - writeDescriptorSet.dstBinding = 0; - // Descriptor count for an inline uniform block contains data sizes of the block(last parameter) - writeDescriptorSet.descriptorCount = sizeof(Object::Material); - // Chain inline uniform block structure - writeDescriptorSet.pNext = &writeDescriptorSetInlineUniformBlock; - - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - } - - void preparePipelines() - { - /* - [POI] Pipeline layout usin two sets, one for the scene matrices and one for the per-object inline uniform blocks - */ - std::vector setLayouts = { - descriptorSetLayouts.scene, // Set 0 = Scene matrices - descriptorSetLayouts.object // Set 1 = Object inline uniform block - }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - - // We use push constants for passing object positions - std::vector pushConstantRanges = { - vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::vec3), 0), - }; - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); - - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_FRONT_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal }); - - shaderStages[0] = loadShader(getShadersPath() + "inlineuniformblocks/pbr.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "inlineuniformblocks/pbr.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f)); - uniformData.camPos = camera.position * glm::vec3(-1.0f, 1.0f, -1.0f); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - /* - [POI] Update descriptor sets at runtime, called from the UI to randomize materials - */ - void updateMaterials() { - // Setup random materials for every object in the scene - for (uint32_t i = 0; i < objects.size(); i++) { - objects[i].setRandomMaterial(!benchmark.active); - } - - for (auto &object : objects) { - /* - [POI] New structure that defines size and data of the inline uniform block needs to be chained into the write descriptor set - We will be using this inline uniform block to pass per-object material information to the fragment shader - */ - VkWriteDescriptorSetInlineUniformBlockEXT writeDescriptorSetInlineUniformBlock{}; - writeDescriptorSetInlineUniformBlock.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT; - writeDescriptorSetInlineUniformBlock.dataSize = sizeof(Object::Material); - // Uniform data for the inline block - writeDescriptorSetInlineUniformBlock.pData = &object.material; - - /* - [POI] Update the object's inline uniform block - */ - VkWriteDescriptorSet writeDescriptorSet{}; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; - writeDescriptorSet.dstSet = object.descriptorSet; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.descriptorCount = sizeof(Object::Material); - writeDescriptorSet.pNext = &writeDescriptorSetInlineUniformBlock; - - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->button("Randomize")) { - updateMaterials(); - } - } - -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/inputattachments/inputattachments.cpp b/examples/inputattachments/inputattachments.cpp deleted file mode 100644 index 24b5130f..00000000 --- a/examples/inputattachments/inputattachments.cpp +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Vulkan Example - Using input attachments - * - * Copyright (C) 2018-2024 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - * - * Summary: - * Input attachments can be used to read attachment contents from a previous sub pass - * at the same pixel position within a single render pass - */ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - vkglTF::Model scene; - - struct UBOMatrices { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - } uboMatrices; - - struct UBOParams { - glm::vec2 brightnessContrast = glm::vec2(0.5f, 1.8f); - glm::vec2 range = glm::vec2(0.6f, 1.0f); - int32_t attachmentIndex = 1; - } uboParams; - - struct { - vks::Buffer matrices; - vks::Buffer params; - } uniformBuffers; - - struct { - VkPipeline attachmentWrite{ VK_NULL_HANDLE }; - VkPipeline attachmentRead{ VK_NULL_HANDLE }; - } pipelines; - - struct { - VkPipelineLayout attachmentWrite{ VK_NULL_HANDLE }; - VkPipelineLayout attachmentRead{ VK_NULL_HANDLE }; - } pipelineLayouts; - - struct { - VkDescriptorSet attachmentWrite{ VK_NULL_HANDLE }; - std::vector attachmentRead{ VK_NULL_HANDLE }; - } descriptorSets; - - struct { - VkDescriptorSetLayout attachmentWrite{ VK_NULL_HANDLE }; - VkDescriptorSetLayout attachmentRead{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - struct FrameBufferAttachment { - VkImage image{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - VkImageView view{ VK_NULL_HANDLE }; - VkFormat format; - }; - struct Attachments { - FrameBufferAttachment color, depth; - }; - std::vector attachments; - VkExtent2D attachmentSize{}; - - const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; - - VulkanExample() : VulkanExampleBase() - { - title = "Input attachments"; - camera.type = Camera::CameraType::firstperson; - camera.movementSpeed = 2.5f; - camera.setPosition(glm::vec3(1.65f, 1.75f, -6.15f)); - camera.setRotation(glm::vec3(-12.75f, 380.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - ui.subpass = 1; - } - - ~VulkanExample() - { - if (device) { - for (uint32_t i = 0; i < attachments.size(); i++) { - vkDestroyImageView(device, attachments[i].color.view, nullptr); - vkDestroyImage(device, attachments[i].color.image, nullptr); - vkFreeMemory(device, attachments[i].color.memory, nullptr); - vkDestroyImageView(device, attachments[i].depth.view, nullptr); - vkDestroyImage(device, attachments[i].depth.image, nullptr); - vkFreeMemory(device, attachments[i].depth.memory, nullptr); - } - - vkDestroyPipeline(device, pipelines.attachmentRead, nullptr); - vkDestroyPipeline(device, pipelines.attachmentWrite, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayouts.attachmentWrite, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.attachmentRead, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.attachmentWrite, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.attachmentRead, nullptr); - - uniformBuffers.matrices.destroy(); - uniformBuffers.params.destroy(); - } - } - - void clearAttachment(FrameBufferAttachment* attachment) - { - vkDestroyImageView(device, attachment->view, nullptr); - vkDestroyImage(device, attachment->image, nullptr); - vkFreeMemory(device, attachment->memory, nullptr); - } - - // Create a frame buffer attachment - void createAttachment(VkFormat format, VkImageUsageFlags usage, FrameBufferAttachment *attachment) - { - VkImageAspectFlags aspectMask = 0; - VkImageLayout imageLayout; - - attachment->format = format; - - if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { - aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } - if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } - - VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = format; - imageCI.extent.width = width; - imageCI.extent.height = height; - imageCI.extent.depth = 1; - imageCI.mipLevels = 1; - imageCI.arrayLayers = 1; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - // VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT flag is required for input attachments; - imageCI.usage = usage | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; - imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &attachment->image)); - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, attachment->image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &attachment->memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, attachment->image, attachment->memory, 0)); - - VkImageViewCreateInfo imageViewCI = vks::initializers::imageViewCreateInfo(); - imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageViewCI.format = format; - imageViewCI.subresourceRange = {}; - imageViewCI.subresourceRange.aspectMask = aspectMask; - imageViewCI.subresourceRange.baseMipLevel = 0; - imageViewCI.subresourceRange.levelCount = 1; - imageViewCI.subresourceRange.baseArrayLayer = 0; - imageViewCI.subresourceRange.layerCount = 1; - imageViewCI.image = attachment->image; - VK_CHECK_RESULT(vkCreateImageView(device, &imageViewCI, nullptr, &attachment->view)); - } - - // Override framebuffer setup from base class - void setupFrameBuffer() - { - // If the window is resized, all the framebuffers/attachments used in our composition passes need to be recreated - if (attachmentSize.width != width || attachmentSize.height != height) - { - attachmentSize = { width, height }; - - for (auto i = 0; i < attachments.size(); i++) { - clearAttachment(&attachments[i].color); - clearAttachment(&attachments[i].depth); - } - - // SRS - Recreate attachments and descriptors in case number of swapchain images has changed on resize - attachments.resize(swapChain.images.size()); - for (auto i = 0; i < attachments.size(); i++) { - createAttachment(colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &attachments[i].color); - createAttachment(depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &attachments[i].depth); - } - - vkDestroyPipelineLayout(device, pipelineLayouts.attachmentWrite, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.attachmentRead, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.attachmentWrite, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.attachmentRead, nullptr); - vkDestroyDescriptorPool(device, descriptorPool, nullptr); - - // Since the framebuffers/attachments are referred in the descriptor sets, these need to be updated on resize - setupDescriptors(); - } - - VkImageView views[3]; - - VkFramebufferCreateInfo frameBufferCI{}; - frameBufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - frameBufferCI.renderPass = renderPass; - frameBufferCI.attachmentCount = 3; - frameBufferCI.pAttachments = views; - frameBufferCI.width = width; - frameBufferCI.height = height; - frameBufferCI.layers = 1; - - frameBuffers.resize(swapChain.images.size()); - for (uint32_t i = 0; i < frameBuffers.size(); i++) - { - views[0] = swapChain.imageViews[i]; - views[1] = attachments[i].color.view; - views[2] = attachments[i].depth.view; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCI, nullptr, &frameBuffers[i])); - } - } - - // Override render pass setup from base class - void setupRenderPass() - { - attachmentSize = { width, height }; - - attachments.resize(swapChain.images.size()); - for (auto i = 0; i < attachments.size(); i++) { - createAttachment(colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &attachments[i].color); - createAttachment(depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &attachments[i].depth); - } - - std::array attachments{}; - - // Swap chain image color attachment - // Will be transitioned to present layout - attachments[0].format = swapChain.colorFormat; - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - // Input attachments - // These will be written in the first subpass, transitioned to input attachments - // and then read in the secod subpass - - // Color - attachments[1].format = colorFormat; - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[1].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - // Depth - attachments[2].format = depthFormat; - attachments[2].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[2].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - std::array subpassDescriptions{}; - - /* - First subpass - Fill the color and depth attachments - */ - VkAttachmentReference colorReference = { 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - VkAttachmentReference depthReference = { 2, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; - - subpassDescriptions[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescriptions[0].colorAttachmentCount = 1; - subpassDescriptions[0].pColorAttachments = &colorReference; - subpassDescriptions[0].pDepthStencilAttachment = &depthReference; - - /* - Second subpass - Input attachment read and swap chain color attachment write - */ - - // Color reference (target) for this sub pass is the swap chain color attachment - VkAttachmentReference colorReferenceSwapchain = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - subpassDescriptions[1].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescriptions[1].colorAttachmentCount = 1; - subpassDescriptions[1].pColorAttachments = &colorReferenceSwapchain; - - // Color and depth attachment written to in first sub pass will be used as input attachments to be read in the fragment shader - VkAttachmentReference inputReferences[2]; - inputReferences[0] = { 1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; - inputReferences[1] = { 2, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; - - // Use the attachments filled in the first pass as input attachments - subpassDescriptions[1].inputAttachmentCount = 2; - subpassDescriptions[1].pInputAttachments = inputReferences; - - /* - Subpass dependencies for layout transitions - */ - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // This dependency transitions the input attachment from color attachment to shader read - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = 1; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[2].srcSubpass = 0; - dependencies[2].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[2].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[2].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[2].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[2].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[2].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassInfoCI{}; - renderPassInfoCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfoCI.attachmentCount = static_cast(attachments.size()); - renderPassInfoCI.pAttachments = attachments.data(); - renderPassInfoCI.subpassCount = static_cast(subpassDescriptions.size()); - renderPassInfoCI.pSubpasses = subpassDescriptions.data(); - renderPassInfoCI.dependencyCount = static_cast(dependencies.size()); - renderPassInfoCI.pDependencies = dependencies.data(); - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfoCI, nullptr, &renderPass)); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[3]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; - clearValues[1].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; - clearValues[2].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 3; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - /* - First sub pass - Fills the attachments - */ - { - vks::debugutils::cmdBeginLabel(drawCmdBuffers[i], "Subpass 0: Writing attachments", { 1.0f, 0.78f, 0.05f, 1.0f }); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.attachmentWrite); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.attachmentWrite, 0, 1, &descriptorSets.attachmentWrite, 0, NULL); - scene.draw(drawCmdBuffers[i]); - - vks::debugutils::cmdEndLabel(drawCmdBuffers[i]); - } - - /* - Second sub pass - Render a full screen quad, reading from the previously written attachments via input attachments - */ - { - vks::debugutils::cmdBeginLabel(drawCmdBuffers[i], "Subpass 1: Reading attachments", { 0.0f, 0.5f, 1.0f, 1.0f }); - - vkCmdNextSubpass(drawCmdBuffers[i], VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.attachmentRead); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.attachmentRead, 0, 1, &descriptorSets.attachmentRead[i], 0, NULL); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - vks::debugutils::cmdEndLabel(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - scene.loadFromFile(getAssetPath() + "models/treasure_smooth.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void updateAttachmentReadDescriptors(uint32_t index) - { - // Image descriptors for the input attachments read by the shader - std::vector descriptors = { - vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments[index].color.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments[index].depth.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - }; - std::vector writeDescriptorSets = { - // Binding 0: Color input attachment - vks::initializers::writeDescriptorSet(descriptorSets.attachmentRead[index], VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 0, &descriptors[0]), - // Binding 1: Depth input attachment - vks::initializers::writeDescriptorSet(descriptorSets.attachmentRead[index], VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, &descriptors[1]), - // Binding 2: Display parameters uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.attachmentRead[index], VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &uniformBuffers.params.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void setupDescriptors() - { - /* - Pool - */ - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, static_cast(attachments.size()) + 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(attachments.size()) + 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, static_cast(attachments.size()) * 2 + 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), static_cast(attachments.size()) + 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - /* - Attachment write - */ - { - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.attachmentWrite)); - - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.attachmentWrite, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.attachmentWrite)); - - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.attachmentWrite, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.attachmentWrite)); - - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSets.attachmentWrite, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.matrices.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - - /* - Attachment read - */ - std::vector setLayoutBindings = { - // Binding 0: Color input attachment - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // Binding 1: Depth input attachment - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 2: Display parameters uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayouts.attachmentRead)); - - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.attachmentRead, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.attachmentRead)); - - descriptorSets.attachmentRead.resize(attachments.size()); - for (auto i = 0; i < descriptorSets.attachmentRead.size(); i++) { - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.attachmentRead, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.attachmentRead[i])); - updateAttachmentReadDescriptors(i); - } - - } - - void preparePipelines() - { - std::array shaderStages; - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(); - - pipelineCI.renderPass = renderPass; - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - /* - Attachment write - */ - - // Pipeline will be used in first sub pass - pipelineCI.subpass = 0; - pipelineCI.layout = pipelineLayouts.attachmentWrite; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal}); - - shaderStages[0] = loadShader(getShadersPath() + "inputattachments/attachmentwrite.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "inputattachments/attachmentwrite.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.attachmentWrite)); - - /* - Attachment read - */ - - // Pipeline will be used in second sub pass - pipelineCI.subpass = 1; - pipelineCI.layout = pipelineLayouts.attachmentRead; - - VkPipelineVertexInputStateCreateInfo emptyInputStateCI{}; - emptyInputStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - - pipelineCI.pVertexInputState = &emptyInputStateCI; - colorBlendStateCI.attachmentCount = 1; - rasterizationStateCI.cullMode = VK_CULL_MODE_NONE; - depthStencilStateCI.depthWriteEnable = VK_FALSE; - - shaderStages[0] = loadShader(getShadersPath() + "inputattachments/attachmentread.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "inputattachments/attachmentread.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.attachmentRead)); - } - - void prepareUniformBuffers() - { - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.matrices, sizeof(uboMatrices)); - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.params, sizeof(uboParams)); - VK_CHECK_RESULT(uniformBuffers.matrices.map()); - VK_CHECK_RESULT(uniformBuffers.params.map()); - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - uboMatrices.projection = camera.matrices.perspective; - uboMatrices.view = camera.matrices.view; - uboMatrices.model = glm::mat4(1.0f); - memcpy(uniformBuffers.matrices.mapped, &uboMatrices, sizeof(uboMatrices)); - memcpy(uniformBuffers.params.mapped, &uboParams, sizeof(uboParams)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->text("Input attachment"); - if (overlay->comboBox("##attachment", &uboParams.attachmentIndex, { "color", "depth" })) { - updateUniformBuffers(); - } - switch (uboParams.attachmentIndex) { - case 0: - overlay->text("Brightness"); - if (overlay->sliderFloat("##b", &uboParams.brightnessContrast[0], 0.0f, 2.0f)) { - updateUniformBuffers(); - } - overlay->text("Contrast"); - if (overlay->sliderFloat("##c", &uboParams.brightnessContrast[1], 0.0f, 4.0f)) { - updateUniformBuffers(); - } - break; - case 1: - overlay->text("Visible range"); - if (overlay->sliderFloat("min", &uboParams.range[0], 0.0f, uboParams.range[1])) { - updateUniformBuffers(); - } - if (overlay->sliderFloat("max", &uboParams.range[1], uboParams.range[0], 1.0f)) { - updateUniformBuffers(); - } - break; - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/instancing/instancing.cpp b/examples/instancing/instancing.cpp deleted file mode 100644 index 9050cb71..00000000 --- a/examples/instancing/instancing.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/* -* Vulkan Example - Instanced mesh rendering, uses a separate vertex buffer for instanced data -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -#if defined(__ANDROID__) -#define INSTANCE_COUNT 4096 -#else -#define INSTANCE_COUNT 8192 -#endif - -class VulkanExample : public VulkanExampleBase -{ -public: - - struct { - vks::Texture2DArray rocks; - vks::Texture2D planet; - } textures{}; - - struct { - vkglTF::Model rock; - vkglTF::Model planet; - } models{}; - - // We provide position, rotation and scale per mesh instance - struct InstanceData { - glm::vec3 pos; - glm::vec3 rot; - float scale{ 0.0f }; - uint32_t texIndex{ 0 }; - }; - // Contains the instanced data - struct InstanceBuffer { - VkBuffer buffer{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - size_t size = 0; - VkDescriptorBufferInfo descriptor{ VK_NULL_HANDLE }; - } instanceBuffer; - - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - glm::vec4 lightPos = glm::vec4(0.0f, -5.0f, 0.0f, 1.0f); - float locSpeed = 0.0f; - float globSpeed = 0.0f; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - struct { - VkPipeline instancedRocks{ VK_NULL_HANDLE }; - VkPipeline planet{ VK_NULL_HANDLE }; - VkPipeline starfield{ VK_NULL_HANDLE }; - } pipelines; - - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - struct { - VkDescriptorSet instancedRocks{ VK_NULL_HANDLE }; - VkDescriptorSet planet{ VK_NULL_HANDLE }; - } descriptorSets; - - VulkanExample() : VulkanExampleBase() - { - title = "Instanced mesh rendering"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(5.5f, -1.85f, -18.5f)); - camera.setRotation(glm::vec3(-17.2f, -4.7f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 1.0f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.instancedRocks, nullptr); - vkDestroyPipeline(device, pipelines.planet, nullptr); - vkDestroyPipeline(device, pipelines.starfield, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyBuffer(device, instanceBuffer.buffer, nullptr); - vkFreeMemory(device, instanceBuffer.memory, nullptr); - textures.rocks.destroy(); - textures.planet.destroy(); - uniformBuffer.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - }; - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - - // Star field - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.planet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.starfield); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - // Planet - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.planet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.planet); - models.planet.draw(drawCmdBuffers[i]); - - // Instanced rocks - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.instancedRocks, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.instancedRocks); - // Binding point 0 : Mesh vertex buffer - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &models.rock.vertices.buffer, offsets); - // Binding point 1 : Instance data buffer - vkCmdBindVertexBuffers(drawCmdBuffers[i], 1, 1, &instanceBuffer.buffer, offsets); - // Bind index buffer - vkCmdBindIndexBuffer(drawCmdBuffers[i], models.rock.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - - // Render instances - vkCmdDrawIndexed(drawCmdBuffers[i], models.rock.indices.count, INSTANCE_COUNT, 0, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.rock.loadFromFile(getAssetPath() + "models/rock01.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.planet.loadFromFile(getAssetPath() + "models/lavaplanet.gltf", vulkanDevice, queue, glTFLoadingFlags); - - textures.planet.loadFromFile(getAssetPath() + "textures/lavaplanet_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.rocks.loadFromFile(getAssetPath() + "textures/texturearray_rocks_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader combined sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - VkDescriptorSetAllocateInfo descripotrSetAllocInfo; - std::vector writeDescriptorSets; - - descripotrSetAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - // Instanced rocks - // Binding 0 : Vertex shader uniform buffer - // Binding 1 : Color map - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descripotrSetAllocInfo, &descriptorSets.instancedRocks)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.instancedRocks, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.instancedRocks, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.rocks.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Planet - // Binding 0 : Vertex shader uniform buffer - // Binding 1 : Color map - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descripotrSetAllocInfo, &descriptorSets.planet)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.planet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.planet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.planet.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState =vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // This example uses two different input states, one for the instanced part and one for non-instanced rendering - VkPipelineVertexInputStateCreateInfo inputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - std::vector bindingDescriptions; - std::vector attributeDescriptions; - - // Vertex input bindings - // The instancing pipeline uses a vertex input state with two bindings - bindingDescriptions = { - // Binding point 0: Mesh vertex layout description at per-vertex rate - vks::initializers::vertexInputBindingDescription(0, sizeof(vkglTF::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - // Binding point 1: Instanced data at per-instance rate - vks::initializers::vertexInputBindingDescription(1, sizeof(InstanceData), VK_VERTEX_INPUT_RATE_INSTANCE) - }; - - // Vertex attribute bindings - // Note that the shader declaration for per-vertex and per-instance attributes is the same, the different input rates are only stored in the bindings: - // instanced.vert: - // layout (location = 0) in vec3 inPos; Per-Vertex - // ... - // layout (location = 4) in vec3 instancePos; Per-Instance - attributeDescriptions = { - // Per-vertex attributes - // These are advanced for each vertex fetched by the vertex shader - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Location 0: Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Location 1: Normal - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32_SFLOAT, sizeof(float) * 6), // Location 2: Texture coordinates - vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 8), // Location 3: Color - // Per-Instance attributes - // These are advanced for each instance rendered - vks::initializers::vertexInputAttributeDescription(1, 4, VK_FORMAT_R32G32B32_SFLOAT, 0), // Location 4: Position - vks::initializers::vertexInputAttributeDescription(1, 5, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Location 5: Rotation - vks::initializers::vertexInputAttributeDescription(1, 6, VK_FORMAT_R32_SFLOAT,sizeof(float) * 6), // Location 6: Scale - vks::initializers::vertexInputAttributeDescription(1, 7, VK_FORMAT_R32_SINT, sizeof(float) * 7), // Location 7: Texture array layer index - }; - inputState.pVertexBindingDescriptions = bindingDescriptions.data(); - inputState.pVertexAttributeDescriptions = attributeDescriptions.data(); - - pipelineCI.pVertexInputState = &inputState; - - // Instancing pipeline - shaderStages[0] = loadShader(getShadersPath() + "instancing/instancing.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "instancing/instancing.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Use all input bindings and attribute descriptions - inputState.vertexBindingDescriptionCount = static_cast(bindingDescriptions.size()); - inputState.vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size()); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.instancedRocks)); - - // Planet rendering pipeline - shaderStages[0] = loadShader(getShadersPath() + "instancing/planet.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "instancing/planet.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Only use the non-instanced input bindings and attribute descriptions - inputState.vertexBindingDescriptionCount = 1; - inputState.vertexAttributeDescriptionCount = 4; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.planet)); - - // Star field pipeline - rasterizationState.cullMode = VK_CULL_MODE_NONE; - depthStencilState.depthWriteEnable = VK_FALSE; - shaderStages[0] = loadShader(getShadersPath() + "instancing/starfield.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "instancing/starfield.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Vertices are generated in the vertex shader - inputState.vertexBindingDescriptionCount = 0; - inputState.vertexAttributeDescriptionCount = 0; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.starfield)); - } - - // Create a buffer with per-instance data that is sourced in the shaders - void prepareInstanceData() - { - std::vector instanceData; - instanceData.resize(INSTANCE_COUNT); - - std::default_random_engine rndGenerator(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::uniform_real_distribution uniformDist(0.0, 1.0); - std::uniform_int_distribution rndTextureIndex(0, textures.rocks.layerCount); - - // Distribute rocks randomly on two different rings - for (auto i = 0; i < INSTANCE_COUNT / 2; i++) { - glm::vec2 ring0 { 7.0f, 11.0f }; - glm::vec2 ring1 { 14.0f, 18.0f }; - - float rho, theta; - - // Inner ring - rho = sqrt((pow(ring0[1], 2.0f) - pow(ring0[0], 2.0f)) * uniformDist(rndGenerator) + pow(ring0[0], 2.0f)); - theta = static_cast(2.0f * M_PI * uniformDist(rndGenerator)); - instanceData[i].pos = glm::vec3(rho*cos(theta), uniformDist(rndGenerator) * 0.5f - 0.25f, rho*sin(theta)); - instanceData[i].rot = glm::vec3(M_PI * uniformDist(rndGenerator), M_PI * uniformDist(rndGenerator), M_PI * uniformDist(rndGenerator)); - instanceData[i].scale = 1.5f + uniformDist(rndGenerator) - uniformDist(rndGenerator); - instanceData[i].texIndex = rndTextureIndex(rndGenerator); - instanceData[i].scale *= 0.75f; - - // Outer ring - rho = sqrt((pow(ring1[1], 2.0f) - pow(ring1[0], 2.0f)) * uniformDist(rndGenerator) + pow(ring1[0], 2.0f)); - theta = static_cast(2.0f * M_PI * uniformDist(rndGenerator)); - instanceData[i + INSTANCE_COUNT / 2].pos = glm::vec3(rho*cos(theta), uniformDist(rndGenerator) * 0.5f - 0.25f, rho*sin(theta)); - instanceData[i + INSTANCE_COUNT / 2].rot = glm::vec3(M_PI * uniformDist(rndGenerator), M_PI * uniformDist(rndGenerator), M_PI * uniformDist(rndGenerator)); - instanceData[i + INSTANCE_COUNT / 2].scale = 1.5f + uniformDist(rndGenerator) - uniformDist(rndGenerator); - instanceData[i + INSTANCE_COUNT / 2].texIndex = rndTextureIndex(rndGenerator); - instanceData[i + INSTANCE_COUNT / 2].scale *= 0.75f; - } - - instanceBuffer.size = instanceData.size() * sizeof(InstanceData); - - // Staging - // Instanced data is static, copy to device local memory - // This results in better performance - - struct { - VkDeviceMemory memory; - VkBuffer buffer; - } stagingBuffer; - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - instanceBuffer.size, - &stagingBuffer.buffer, - &stagingBuffer.memory, - instanceData.data())); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - instanceBuffer.size, - &instanceBuffer.buffer, - &instanceBuffer.memory)); - - // Copy to staging buffer - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - VkBufferCopy copyRegion = { }; - copyRegion.size = instanceBuffer.size; - vkCmdCopyBuffer( - copyCmd, - stagingBuffer.buffer, - instanceBuffer.buffer, - 1, - ©Region); - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - instanceBuffer.descriptor.range = instanceBuffer.size; - instanceBuffer.descriptor.buffer = instanceBuffer.buffer; - instanceBuffer.descriptor.offset = 0; - - // Destroy staging resources - vkDestroyBuffer(device, stagingBuffer.buffer, nullptr); - vkFreeMemory(device, stagingBuffer.memory, nullptr); - } - - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - - updateUniformBuffer(); - } - - void updateUniformBuffer() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - - if (!paused) { - uniformData.locSpeed += frameTimer * 0.35f; - uniformData.globSpeed += frameTimer * 0.01f; - } - - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareInstanceData(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - { - return; - } - updateUniformBuffer(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Statistics")) { - overlay->text("Instances: %d", INSTANCE_COUNT); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/meshshader/meshshader.cpp b/examples/meshshader/meshshader.cpp deleted file mode 100644 index 38bfdfe2..00000000 --- a/examples/meshshader/meshshader.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Vulkan Example - Basic sample for using mesh and task shader to replace the traditional vertex pipeline - * - * Copyright (C) 2022-2023 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -#include "vulkanexamplebase.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - struct UniformData { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - } uniformData; - vks::Buffer uniformBuffer; - - uint32_t indexCount{ 0 }; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - PFN_vkCmdDrawMeshTasksEXT vkCmdDrawMeshTasksEXT{ VK_NULL_HANDLE }; - - VkPhysicalDeviceMeshShaderFeaturesEXT enabledMeshShaderFeatures{}; - - VulkanExample() : VulkanExampleBase() - { - title = "Mesh shaders"; - timerSpeed *= 0.25f; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 15.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -5.0f)); - - // The mesh shader extension requires at least Vulkan Core 1.1 - apiVersion = VK_API_VERSION_1_1; - - // Extensions required by mesh shading - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_EXT_MESH_SHADER_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); - - // Required by VK_KHR_spirv_1_4 - enabledDeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); - - // We need to enable the mesh and task shader feature using a new struct introduced with the extension - enabledMeshShaderFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT; - enabledMeshShaderFeatures.meshShader = VK_TRUE; - enabledMeshShaderFeatures.taskShader = VK_TRUE; - - deviceCreatepNextChain = &enabledMeshShaderFeatures; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 1.0f } };; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - // Use mesh and task shader to draw the scene - vkCmdDrawMeshTasksEXT(drawCmdBuffers[i], 1, 1, 1); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_MESH_BIT_EXT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayoutInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutInfo, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector modelWriteDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(modelWriteDescriptorSets.size()), modelWriteDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Not using a vertex shader, mesh shading doesn't require vertex input state - pipelineCI.pInputAssemblyState = nullptr; - pipelineCI.pVertexInputState = nullptr; - - // Instead of a vertex shader, we use a mesh and task shader - shaderStages[0] = loadShader(getShadersPath() + "meshshader/meshshader.mesh.spv", VK_SHADER_STAGE_MESH_BIT_EXT); - shaderStages[1] = loadShader(getShadersPath() + "meshshader/meshshader.task.spv", VK_SHADER_STAGE_TASK_BIT_EXT); - - shaderStages[2] = loadShader(getShadersPath() + "meshshader/meshshader.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.model = glm::mat4(1.0f); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - - // Get the function pointer of the mesh shader drawing funtion - vkCmdDrawMeshTasksEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdDrawMeshTasksEXT")); - - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/multisampling/multisampling.cpp b/examples/multisampling/multisampling.cpp deleted file mode 100644 index 430ab642..00000000 --- a/examples/multisampling/multisampling.cpp +++ /dev/null @@ -1,550 +0,0 @@ -/* -* Vulkan Example - Multisampling using resolve attachments (MSAA) -* -* This sample shows how to do multisampled anti aliasing using built-in hardware via resolve attachments -* These are special attachments that a multi-sampled is resolved to using a fixed sample pattern -* -* Copyright (C) 2016-2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool useSampleShading = false; - VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; - - vkglTF::Model model; - - struct UniformData { - glm::mat4 projection; - glm::mat4 model; - glm::vec4 lightPos = glm::vec4(5.0f, -5.0f, 5.0f, 1.0f); - } uniformData; - vks::Buffer uniformBuffer; - - struct { - VkPipeline MSAA{ VK_NULL_HANDLE }; - VkPipeline MSAASampleShading{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkExtent2D attachmentSize{}; - - // Holds the Vulkan resources required for the final multi sample output target - struct MultiSampleTarget { - struct { - VkImage image{ VK_NULL_HANDLE }; - VkImageView view{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - } color; - struct { - VkImage image{ VK_NULL_HANDLE }; - VkImageView view{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - } depth; - } multisampleTarget; - - VulkanExample() : VulkanExampleBase() - { - title = "Multisampling"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - camera.setRotation(glm::vec3(0.0f, -90.0f, 0.0f)); - camera.setTranslation(glm::vec3(2.5f, 2.5f, -7.5f)); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.MSAA, nullptr); - vkDestroyPipeline(device, pipelines.MSAASampleShading, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - // Destroy MSAA target - vkDestroyImage(device, multisampleTarget.color.image, nullptr); - vkDestroyImageView(device, multisampleTarget.color.view, nullptr); - vkFreeMemory(device, multisampleTarget.color.memory, nullptr); - vkDestroyImage(device, multisampleTarget.depth.image, nullptr); - vkDestroyImageView(device, multisampleTarget.depth.view, nullptr); - vkFreeMemory(device, multisampleTarget.depth.memory, nullptr); - - uniformBuffer.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Enable sample rate shading filtering if supported - if (deviceFeatures.sampleRateShading) { - enabledFeatures.sampleRateShading = VK_TRUE; - } - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - } - - // Creates a multi sample render target (image and view) that is used to resolve - // into the visible frame buffer target in the render pass - void setupMultisampleTarget() - { - // Check if device supports requested sample count for color and depth frame buffer - assert((deviceProperties.limits.framebufferColorSampleCounts & sampleCount) && (deviceProperties.limits.framebufferDepthSampleCounts & sampleCount)); - - // Color target - VkImageCreateInfo info = vks::initializers::imageCreateInfo(); - info.imageType = VK_IMAGE_TYPE_2D; - info.format = swapChain.colorFormat; - info.extent.width = width; - info.extent.height = height; - info.extent.depth = 1; - info.mipLevels = 1; - info.arrayLayers = 1; - info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - info.tiling = VK_IMAGE_TILING_OPTIMAL; - info.samples = sampleCount; - // Image will only be used as a transient target - info.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VK_CHECK_RESULT(vkCreateImage(device, &info, nullptr, &multisampleTarget.color.image)); - - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, multisampleTarget.color.image, &memReqs); - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - memAlloc.allocationSize = memReqs.size; - // We prefer a lazily allocated memory type - // This means that the memory gets allocated when the implementation sees fit, e.g. when first using the images - VkBool32 lazyMemTypePresent; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, &lazyMemTypePresent); - if (!lazyMemTypePresent) - { - // If this is not available, fall back to device local memory - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - } - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &multisampleTarget.color.memory)); - vkBindImageMemory(device, multisampleTarget.color.image, multisampleTarget.color.memory, 0); - - // Create image view for the MSAA target - VkImageViewCreateInfo viewInfo = vks::initializers::imageViewCreateInfo(); - viewInfo.image = multisampleTarget.color.image; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.format = swapChain.colorFormat; - viewInfo.components.r = VK_COMPONENT_SWIZZLE_R; - viewInfo.components.g = VK_COMPONENT_SWIZZLE_G; - viewInfo.components.b = VK_COMPONENT_SWIZZLE_B; - viewInfo.components.a = VK_COMPONENT_SWIZZLE_A; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.layerCount = 1; - - VK_CHECK_RESULT(vkCreateImageView(device, &viewInfo, nullptr, &multisampleTarget.color.view)); - - // Depth target - info.imageType = VK_IMAGE_TYPE_2D; - info.format = depthFormat; - info.extent.width = width; - info.extent.height = height; - info.extent.depth = 1; - info.mipLevels = 1; - info.arrayLayers = 1; - info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - info.tiling = VK_IMAGE_TILING_OPTIMAL; - info.samples = sampleCount; - // Image will only be used as a transient target - info.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VK_CHECK_RESULT(vkCreateImage(device, &info, nullptr, &multisampleTarget.depth.image)); - - vkGetImageMemoryRequirements(device, multisampleTarget.depth.image, &memReqs); - memAlloc = vks::initializers::memoryAllocateInfo(); - memAlloc.allocationSize = memReqs.size; - - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, &lazyMemTypePresent); - if (!lazyMemTypePresent) - { - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - } - - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &multisampleTarget.depth.memory)); - vkBindImageMemory(device, multisampleTarget.depth.image, multisampleTarget.depth.memory, 0); - - // Create image view for the MSAA target - viewInfo.image = multisampleTarget.depth.image; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.format = depthFormat; - viewInfo.components.r = VK_COMPONENT_SWIZZLE_R; - viewInfo.components.g = VK_COMPONENT_SWIZZLE_G; - viewInfo.components.b = VK_COMPONENT_SWIZZLE_B; - viewInfo.components.a = VK_COMPONENT_SWIZZLE_A; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (depthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) - viewInfo.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.layerCount = 1; - - VK_CHECK_RESULT(vkCreateImageView(device, &viewInfo, nullptr, &multisampleTarget.depth.view)); - } - - // Setup a render pass for using a multi sampled attachment - // and a resolve attachment that the msaa image is resolved - // to at the end of the render pass - void setupRenderPass() - { - // Overrides the virtual function of the base class - - attachmentSize = { width, height }; - - std::array attachments = {}; - - // Multisampled attachment that we render to - attachments[0].format = swapChain.colorFormat; - attachments[0].samples = sampleCount; - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - // This is the frame buffer attachment to where the multisampled image - // will be resolved to and which will be presented to the swapchain - attachments[1].format = swapChain.colorFormat; - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[1].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - // Multisampled depth attachment we render to - attachments[2].format = depthFormat; - attachments[2].samples = sampleCount; - attachments[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[2].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorReference = {}; - colorReference.attachment = 0; - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthReference = {}; - depthReference.attachment = 2; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - // Resolve attachment reference for the color attachment - VkAttachmentReference resolveReference = {}; - resolveReference.attachment = 1; - resolveReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorReference; - // Pass our resolve attachments to the sub pass - subpass.pResolveAttachments = &resolveReference; - subpass.pDepthStencilAttachment = &depthReference; - - std::array dependencies{}; - - // Depth attachment - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; - dependencies[0].dependencyFlags = 0; - // Color attachment - dependencies[1].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].dstSubpass = 0; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].srcAccessMask = 0; - dependencies[1].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - dependencies[1].dependencyFlags = 0; - - VkRenderPassCreateInfo renderPassInfo = vks::initializers::renderPassCreateInfo(); - renderPassInfo.attachmentCount = static_cast(attachments.size()); - renderPassInfo.pAttachments = attachments.data(); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 2; - renderPassInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass)); - } - - // Frame buffer attachments must match with render pass setup, - // so we need to adjust frame buffer creation to cover our - // multisample target - void setupFrameBuffer() - { - // Overrides the virtual function of the base class - - // SRS - If the window is resized, the MSAA attachments need to be released and recreated - if (attachmentSize.width != width || attachmentSize.height != height) - { - attachmentSize = { width, height }; - - // Destroy MSAA target - vkDestroyImage(device, multisampleTarget.color.image, nullptr); - vkDestroyImageView(device, multisampleTarget.color.view, nullptr); - vkFreeMemory(device, multisampleTarget.color.memory, nullptr); - vkDestroyImage(device, multisampleTarget.depth.image, nullptr); - vkDestroyImageView(device, multisampleTarget.depth.view, nullptr); - vkFreeMemory(device, multisampleTarget.depth.memory, nullptr); - } - - std::array attachments; - - setupMultisampleTarget(); - - attachments[0] = multisampleTarget.color.view; - // attachment[1] = swapchain image - attachments[2] = multisampleTarget.depth.view; - - VkFramebufferCreateInfo frameBufferCreateInfo = {}; - frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - frameBufferCreateInfo.pNext = NULL; - frameBufferCreateInfo.renderPass = renderPass; - frameBufferCreateInfo.attachmentCount = static_cast(attachments.size()); - frameBufferCreateInfo.pAttachments = attachments.data(); - frameBufferCreateInfo.width = width; - frameBufferCreateInfo.height = height; - frameBufferCreateInfo.layers = 1; - - // Create frame buffers for every swap chain image - frameBuffers.resize(swapChain.images.size()); - for (uint32_t i = 0; i < frameBuffers.size(); i++) - { - attachments[1] = swapChain.imageViews[i]; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCreateInfo, nullptr, &frameBuffers[i])); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[3]; - // Clear to a white background for higher contrast - clearValues[0].color = { { 1.0f, 1.0f, 1.0f, 1.0f } }; - clearValues[1].color = { { 1.0f, 1.0f, 1.0f, 1.0f } }; - clearValues[2].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 3; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, useSampleShading ? pipelines.MSAASampleShading : pipelines.MSAA); - model.draw(drawCmdBuffers[i], vkglTF::RenderFlags::BindImages, pipelineLayout); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - model.loadFromFile(getAssetPath() + "models/voyager.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - const std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout uses set 0 for passing vertex shader ubo and set 1 for fragment shader images (taken from glTF model) - const std::vector setLayouts = { - descriptorSetLayout, - vkglTF::descriptorSetLayoutImage, - }; - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), 2); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Setup multi sampling - VkPipelineMultisampleStateCreateInfo multisampleState{}; - multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - // Number of samples to use for rasterization - multisampleState.rasterizationSamples = sampleCount; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color }); - - // MSAA rendering pipeline - shaderStages[0] = loadShader(getShadersPath() + "multisampling/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "multisampling/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.MSAA)); - - if (vulkanDevice->features.sampleRateShading) - { - // MSAA with sample shading pipeline - // Sample shading enables per-sample shading to avoid shader aliasing and smooth out e.g. high frequency texture maps - // Note: This will trade performance for are more stable image - - // Enable per-sample shading (instead of per-fragment) - multisampleState.sampleShadingEnable = VK_TRUE; - // Minimum fraction for sample shading - multisampleState.minSampleShading = 0.25f; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.MSAASampleShading)); - } - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.model = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - // Select the highest sample count usable by the platform - // In a realworld application, this would be a user setting instead - VkSampleCountFlagBits getMaxAvailableSampleCount() - { - VkSampleCountFlags supportedSampleCount = std::min(deviceProperties.limits.framebufferColorSampleCounts, deviceProperties.limits.framebufferDepthSampleCounts); - std::vector< VkSampleCountFlagBits> possibleSampleCounts { - VK_SAMPLE_COUNT_64_BIT, VK_SAMPLE_COUNT_32_BIT, VK_SAMPLE_COUNT_16_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_2_BIT - }; - for (auto& possibleSampleCount : possibleSampleCounts) { - if (supportedSampleCount & possibleSampleCount) { - return possibleSampleCount; - } - } - return VK_SAMPLE_COUNT_1_BIT; - } - - void prepare() - { - sampleCount = getMaxAvailableSampleCount(); - ui.rasterizationSamples = sampleCount; - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (vulkanDevice->features.sampleRateShading) { - if (overlay->header("Settings")) { - if (overlay->checkBox("Sample rate shading", &useSampleShading)) { - buildCommandBuffers(); - } - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/multithreading/multithreading.cpp b/examples/multithreading/multithreading.cpp deleted file mode 100644 index 8f5d7bc1..00000000 --- a/examples/multithreading/multithreading.cpp +++ /dev/null @@ -1,520 +0,0 @@ -/* -* Vulkan Example - Multi threaded command buffer generation and rendering -* -* Copyright (C) 2016-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -#include "threadpool.hpp" -#include "frustum.hpp" - -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool displayStarSphere = true; - - struct { - vkglTF::Model ufo; - vkglTF::Model starSphere; - } models; - - // Shared matrices used for thread push constant blocks - struct { - glm::mat4 projection; - glm::mat4 view; - } matrices; - - struct { - VkPipeline phong{ VK_NULL_HANDLE }; - VkPipeline starsphere{ VK_NULL_HANDLE }; - } pipelines; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkCommandBuffer primaryCommandBuffer{ VK_NULL_HANDLE }; - - // Secondary scene command buffers used to store backdrop and user interface - struct SecondaryCommandBuffers { - VkCommandBuffer background{ VK_NULL_HANDLE }; - VkCommandBuffer ui{ VK_NULL_HANDLE }; - } secondaryCommandBuffers; - - // Number of animated objects to be renderer - // by using threads and secondary command buffers - uint32_t numObjectsPerThread{ 0 }; - - // Multi threaded stuff - // Max. number of concurrent threads - uint32_t numThreads{ 0 }; - - // Use push constants to update shader - // parameters on a per-thread base - struct ThreadPushConstantBlock { - glm::mat4 mvp; - glm::vec3 color; - }; - - struct ObjectData { - glm::mat4 model; - glm::vec3 pos; - glm::vec3 rotation; - float rotationDir; - float rotationSpeed; - float scale; - float deltaT; - float stateT = 0; - bool visible = true; - }; - - struct ThreadData { - VkCommandPool commandPool{ VK_NULL_HANDLE }; - // One command buffer per render object - std::vector commandBuffer; - // One push constant block per render object - std::vector pushConstBlock; - // Per object information (position, rotation, etc.) - std::vector objectData; - }; - std::vector threadData; - - vks::ThreadPool threadPool; - - // Fence to wait for all command buffers to finish before - // presenting to the swap chain - VkFence renderFence{ VK_NULL_HANDLE }; - - // View frustum for culling invisible objects - vks::Frustum frustum; - - std::default_random_engine rndEngine; - - VulkanExample() : VulkanExampleBase() - { - title = "Multi threaded command buffer"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, -0.0f, -32.5f)); - camera.setRotation(glm::vec3(0.0f)); - camera.setRotationSpeed(0.5f); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - // Get number of max. concurrent threads - numThreads = std::thread::hardware_concurrency(); - assert(numThreads > 0); -#if defined(__ANDROID__) - LOGD("numThreads = %d", numThreads); -#else - std::cout << "numThreads = " << numThreads << std::endl; -#endif - threadPool.setThreadCount(numThreads); - numObjectsPerThread = 512 / numThreads; - rndEngine.seed(benchmark.active ? 0 : (unsigned)time(nullptr)); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.phong, nullptr); - vkDestroyPipeline(device, pipelines.starsphere, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - for (auto& thread : threadData) { - vkFreeCommandBuffers(device, thread.commandPool, static_cast(thread.commandBuffer.size()), thread.commandBuffer.data()); - vkDestroyCommandPool(device, thread.commandPool, nullptr); - } - vkDestroyFence(device, renderFence, nullptr); - } - } - - float rnd(float range) - { - std::uniform_real_distribution rndDist(0.0f, range); - return rndDist(rndEngine); - } - - // Create all threads and initialize shader push constants - void prepareMultiThreadedRenderer() - { - // Since this demo updates the command buffers on each frame - // we don't use the per-framebuffer command buffers from the - // base class, and create a single primary command buffer instead - VkCommandBufferAllocateInfo cmdBufAllocateInfo = - vks::initializers::commandBufferAllocateInfo( - cmdPool, - VK_COMMAND_BUFFER_LEVEL_PRIMARY, - 1); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &primaryCommandBuffer)); - - // Create additional secondary CBs for background and ui - cmdBufAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &secondaryCommandBuffers.background)); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &secondaryCommandBuffers.ui)); - - threadData.resize(numThreads); - - float maxX = static_cast(std::floor(std::sqrt(numThreads * numObjectsPerThread))); - uint32_t posX = 0; - uint32_t posZ = 0; - - for (uint32_t i = 0; i < numThreads; i++) { - ThreadData *thread = &threadData[i]; - - // Create one command pool for each thread - VkCommandPoolCreateInfo cmdPoolInfo = vks::initializers::commandPoolCreateInfo(); - cmdPoolInfo.queueFamilyIndex = swapChain.queueNodeIndex; - cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &thread->commandPool)); - - // One secondary command buffer per object that is updated by this thread - thread->commandBuffer.resize(numObjectsPerThread); - // Generate secondary command buffers for each thread - VkCommandBufferAllocateInfo secondaryCmdBufAllocateInfo = - vks::initializers::commandBufferAllocateInfo( - thread->commandPool, - VK_COMMAND_BUFFER_LEVEL_SECONDARY, - static_cast(thread->commandBuffer.size())); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &secondaryCmdBufAllocateInfo, thread->commandBuffer.data())); - - thread->pushConstBlock.resize(numObjectsPerThread); - thread->objectData.resize(numObjectsPerThread); - - for (uint32_t j = 0; j < numObjectsPerThread; j++) { - float theta = 2.0f * float(M_PI) * rnd(1.0f); - float phi = acos(1.0f - 2.0f * rnd(1.0f)); - thread->objectData[j].pos = glm::vec3(sin(phi) * cos(theta), 0.0f, cos(phi)) * 35.0f; - - thread->objectData[j].rotation = glm::vec3(0.0f, rnd(360.0f), 0.0f); - thread->objectData[j].deltaT = rnd(1.0f); - thread->objectData[j].rotationDir = (rnd(100.0f) < 50.0f) ? 1.0f : -1.0f; - thread->objectData[j].rotationSpeed = (2.0f + rnd(4.0f)) * thread->objectData[j].rotationDir; - thread->objectData[j].scale = 0.75f + rnd(0.5f); - - thread->pushConstBlock[j].color = glm::vec3(rnd(1.0f), rnd(1.0f), rnd(1.0f)); - } - } - - } - - // Builds the secondary command buffer for each thread - void threadRenderCode(uint32_t threadIndex, uint32_t cmdBufferIndex, VkCommandBufferInheritanceInfo inheritanceInfo) - { - ThreadData *thread = &threadData[threadIndex]; - ObjectData *objectData = &thread->objectData[cmdBufferIndex]; - - // Check visibility against view frustum using a simple sphere check based on the radius of the mesh - objectData->visible = frustum.checkSphere(objectData->pos, models.ufo.dimensions.radius * 0.5f); - - if (!objectData->visible) - { - return; - } - - VkCommandBufferBeginInfo commandBufferBeginInfo = vks::initializers::commandBufferBeginInfo(); - commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - commandBufferBeginInfo.pInheritanceInfo = &inheritanceInfo; - - VkCommandBuffer cmdBuffer = thread->commandBuffer[cmdBufferIndex]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(cmdBuffer, &commandBufferBeginInfo)); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(cmdBuffer, 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(cmdBuffer, 0, 1, &scissor); - - vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phong); - - // Update - if (!paused) { - objectData->rotation.y += 2.5f * objectData->rotationSpeed * frameTimer; - if (objectData->rotation.y > 360.0f) { - objectData->rotation.y -= 360.0f; - } - objectData->deltaT += 0.15f * frameTimer; - if (objectData->deltaT > 1.0f) - objectData->deltaT -= 1.0f; - objectData->pos.y = sin(glm::radians(objectData->deltaT * 360.0f)) * 2.5f; - } - - objectData->model = glm::translate(glm::mat4(1.0f), objectData->pos); - objectData->model = glm::rotate(objectData->model, -sinf(glm::radians(objectData->deltaT * 360.0f)) * 0.25f, glm::vec3(objectData->rotationDir, 0.0f, 0.0f)); - objectData->model = glm::rotate(objectData->model, glm::radians(objectData->rotation.y), glm::vec3(0.0f, objectData->rotationDir, 0.0f)); - objectData->model = glm::rotate(objectData->model, glm::radians(objectData->deltaT * 360.0f), glm::vec3(0.0f, objectData->rotationDir, 0.0f)); - objectData->model = glm::scale(objectData->model, glm::vec3(objectData->scale)); - - thread->pushConstBlock[cmdBufferIndex].mvp = matrices.projection * matrices.view * objectData->model; - - // Update shader push constant block - // Contains model view matrix - vkCmdPushConstants( - cmdBuffer, - pipelineLayout, - VK_SHADER_STAGE_VERTEX_BIT, - 0, - sizeof(ThreadPushConstantBlock), - &thread->pushConstBlock[cmdBufferIndex]); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(cmdBuffer, 0, 1, &models.ufo.vertices.buffer, offsets); - vkCmdBindIndexBuffer(cmdBuffer, models.ufo.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(cmdBuffer, models.ufo.indices.count, 1, 0, 0, 0); - - VK_CHECK_RESULT(vkEndCommandBuffer(cmdBuffer)); - } - - void updateSecondaryCommandBuffers(VkCommandBufferInheritanceInfo inheritanceInfo) - { - // Secondary command buffer for the sky sphere - VkCommandBufferBeginInfo commandBufferBeginInfo = vks::initializers::commandBufferBeginInfo(); - commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - commandBufferBeginInfo.pInheritanceInfo = &inheritanceInfo; - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - - /* - Background - */ - - VK_CHECK_RESULT(vkBeginCommandBuffer(secondaryCommandBuffers.background, &commandBufferBeginInfo)); - - vkCmdSetViewport(secondaryCommandBuffers.background, 0, 1, &viewport); - vkCmdSetScissor(secondaryCommandBuffers.background, 0, 1, &scissor); - - vkCmdBindPipeline(secondaryCommandBuffers.background, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.starsphere); - - glm::mat4 mvp = matrices.projection * matrices.view; - mvp[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); - mvp = glm::scale(mvp, glm::vec3(2.0f)); - - vkCmdPushConstants( - secondaryCommandBuffers.background, - pipelineLayout, - VK_SHADER_STAGE_VERTEX_BIT, - 0, - sizeof(mvp), - &mvp); - - models.starSphere.draw(secondaryCommandBuffers.background); - - VK_CHECK_RESULT(vkEndCommandBuffer(secondaryCommandBuffers.background)); - - /* - User interface - - With VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, the primary command buffer's content has to be defined - by secondary command buffers, which also applies to the UI overlay command buffer - */ - - VK_CHECK_RESULT(vkBeginCommandBuffer(secondaryCommandBuffers.ui, &commandBufferBeginInfo)); - - vkCmdSetViewport(secondaryCommandBuffers.ui, 0, 1, &viewport); - vkCmdSetScissor(secondaryCommandBuffers.ui, 0, 1, &scissor); - - vkCmdBindPipeline(secondaryCommandBuffers.ui, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.starsphere); - - drawUI(secondaryCommandBuffers.ui); - - VK_CHECK_RESULT(vkEndCommandBuffer(secondaryCommandBuffers.ui)); - } - - // Updates the secondary command buffers using a thread pool - // and puts them into the primary command buffer that's - // lat submitted to the queue for rendering - void updateCommandBuffers(VkFramebuffer frameBuffer) - { - // Contains the list of secondary command buffers to be submitted - std::vector commandBuffers; - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]{}; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - renderPassBeginInfo.framebuffer = frameBuffer; - - // Set target frame buffer - - VK_CHECK_RESULT(vkBeginCommandBuffer(primaryCommandBuffer, &cmdBufInfo)); - - // The primary command buffer does not contain any rendering commands - // These are stored (and retrieved) from the secondary command buffers - vkCmdBeginRenderPass(primaryCommandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - - // Inheritance info for the secondary command buffers - VkCommandBufferInheritanceInfo inheritanceInfo = vks::initializers::commandBufferInheritanceInfo(); - inheritanceInfo.renderPass = renderPass; - // Secondary command buffer also use the currently active framebuffer - inheritanceInfo.framebuffer = frameBuffer; - - // Update secondary sene command buffers - updateSecondaryCommandBuffers(inheritanceInfo); - - if (displayStarSphere) { - commandBuffers.push_back(secondaryCommandBuffers.background); - } - - // Add a job to the thread's queue for each object to be rendered - for (uint32_t t = 0; t < numThreads; t++) - { - for (uint32_t i = 0; i < numObjectsPerThread; i++) - { - threadPool.threads[t]->addJob([=, this] { threadRenderCode(t, i, inheritanceInfo); }); - } - } - - threadPool.wait(); - - // Only submit if object is within the current view frustum - for (uint32_t t = 0; t < numThreads; t++) - { - for (uint32_t i = 0; i < numObjectsPerThread; i++) - { - if (threadData[t].objectData[i].visible) - { - commandBuffers.push_back(threadData[t].commandBuffer[i]); - } - } - } - - // Render ui last - if (ui.visible) { - commandBuffers.push_back(secondaryCommandBuffers.ui); - } - - // Execute render commands from the secondary command buffer - vkCmdExecuteCommands(primaryCommandBuffer, static_cast(commandBuffers.size()), commandBuffers.data()); - - vkCmdEndRenderPass(primaryCommandBuffer); - - VK_CHECK_RESULT(vkEndCommandBuffer(primaryCommandBuffer)); - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.ufo.loadFromFile(getAssetPath() + "models/retroufo_red_lowpoly.gltf",vulkanDevice, queue,glTFLoadingFlags); - models.starSphere.loadFromFile(getAssetPath() + "models/sphere.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(nullptr, 0); - // Push constants for model matrices - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(ThreadPushConstantBlock), 0); - // Push constant ranges are part of the pipeline layout - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages{}; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); - - // Object rendering pipeline - shaderStages[0] = loadShader(getShadersPath() + "multithreading/phong.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "multithreading/phong.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.phong)); - - // Star sphere rendering pipeline - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - depthStencilState.depthWriteEnable = VK_FALSE; - shaderStages[0] = loadShader(getShadersPath() + "multithreading/starsphere.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "multithreading/starsphere.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.starsphere)); - } - - void updateMatrices() - { - matrices.projection = camera.matrices.perspective; - matrices.view = camera.matrices.view; - frustum.update(matrices.projection * matrices.view); - } - - void prepare() - { - VulkanExampleBase::prepare(); - // Create a fence for synchronization - VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); - vkCreateFence(device, &fenceCreateInfo, nullptr, &renderFence); - loadAssets(); - preparePipelines(); - prepareMultiThreadedRenderer(); - updateMatrices(); - prepared = true; - } - - void draw() - { - // Wait for fence to signal that all command buffers are ready - VkResult fenceRes; - do { - fenceRes = vkWaitForFences(device, 1, &renderFence, VK_TRUE, 100000000); - } while (fenceRes == VK_TIMEOUT); - VK_CHECK_RESULT(fenceRes); - vkResetFences(device, 1, &renderFence); - - VulkanExampleBase::prepareFrame(); - - updateCommandBuffers(frameBuffers[currentBuffer]); - - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &primaryCommandBuffer; - - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, renderFence)); - - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateMatrices(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Statistics")) { - overlay->text("Active threads: %d", numThreads); - } - if (overlay->header("Settings")) { - overlay->checkBox("Stars", &displayStarSphere); - } - - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/multiview/multiview.cpp b/examples/multiview/multiview.cpp deleted file mode 100644 index 6c8ff242..00000000 --- a/examples/multiview/multiview.cpp +++ /dev/null @@ -1,742 +0,0 @@ -/* -* Vulkan Example - Multiview (VK_KHR_multiview) -* -* Uses VK_KHR_multiview for simultaneously rendering to multiple views and displays these with barrel distortion using a fragment shader -* -* Copyright (C) 2018-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - struct MultiviewPass { - struct FrameBufferAttachment { - VkImage image{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - VkImageView view{ VK_NULL_HANDLE }; - } color, depth; - VkFramebuffer frameBuffer{ VK_NULL_HANDLE }; - VkRenderPass renderPass{ VK_NULL_HANDLE }; - VkDescriptorImageInfo descriptor{ VK_NULL_HANDLE }; - VkSampler sampler{ VK_NULL_HANDLE }; - VkSemaphore semaphore{ VK_NULL_HANDLE }; - std::vector commandBuffers{}; - std::vector waitFences{}; - } multiviewPass; - - vkglTF::Model scene; - - struct UniformData { - glm::mat4 projection[2]; - glm::mat4 modelview[2]; - glm::vec4 lightPos = glm::vec4(-2.5f, -3.5f, 0.0f, 1.0f); - float distortionAlpha = 0.2f; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VkPipeline viewDisplayPipelines[2]{}; - - VkPhysicalDeviceMultiviewFeaturesKHR physicalDeviceMultiviewFeatures{}; - - // Camera and view properties - float eyeSeparation = 0.08f; - const float focalLength = 0.5f; - const float fov = 90.0f; - const float zNear = 0.1f; - const float zFar = 256.0f; - - VulkanExample() : VulkanExampleBase() - { - title = "Multiview rendering"; - camera.type = Camera::CameraType::firstperson; - camera.setRotation(glm::vec3(0.0f, 90.0f, 0.0f)); - camera.setTranslation(glm::vec3(7.0f, 3.2f, 0.0f)); - camera.movementSpeed = 5.0f; - - // Enable extension required for multiview - enabledDeviceExtensions.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); - - // Reading device properties and features for multiview requires VK_KHR_get_physical_device_properties2 to be enabled - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - - // Enable required extension features - physicalDeviceMultiviewFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR; - physicalDeviceMultiviewFeatures.multiview = VK_TRUE; - deviceCreatepNextChain = &physicalDeviceMultiviewFeatures; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyImageView(device, multiviewPass.color.view, nullptr); - vkDestroyImage(device, multiviewPass.color.image, nullptr); - vkFreeMemory(device, multiviewPass.color.memory, nullptr); - vkDestroyImageView(device, multiviewPass.depth.view, nullptr); - vkDestroyImage(device, multiviewPass.depth.image, nullptr); - vkFreeMemory(device, multiviewPass.depth.memory, nullptr); - vkDestroyRenderPass(device, multiviewPass.renderPass, nullptr); - vkDestroySampler(device, multiviewPass.sampler, nullptr); - vkDestroyFramebuffer(device, multiviewPass.frameBuffer, nullptr); - vkFreeCommandBuffers(device, cmdPool, static_cast(multiviewPass.commandBuffers.size()), multiviewPass.commandBuffers.data()); - vkDestroySemaphore(device, multiviewPass.semaphore, nullptr); - for (auto& fence : multiviewPass.waitFences) { - vkDestroyFence(device, fence, nullptr); - } - for (auto& pipeline : viewDisplayPipelines) { - vkDestroyPipeline(device, pipeline, nullptr); - } - uniformBuffer.destroy(); - } - } - - /* - Prepares all resources required for the multiview attachment - Images, views, attachments, renderpass, framebuffer, etc. - */ - void prepareMultiview() - { - // Example renders to two views (left/right) - const uint32_t multiviewLayerCount = 2; - - /* - Layered depth/stencil framebuffer - */ - { - VkImageCreateInfo imageCI= vks::initializers::imageCreateInfo(); - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = depthFormat; - imageCI.extent = { width, height, 1 }; - imageCI.mipLevels = 1; - imageCI.arrayLayers = multiviewLayerCount; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - imageCI.flags = 0; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &multiviewPass.depth.image)); - - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, multiviewPass.depth.image, &memReqs); - - VkMemoryAllocateInfo memAllocInfo{}; - memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memAllocInfo.allocationSize = 0; - memAllocInfo.memoryTypeIndex = 0; - - VkImageViewCreateInfo depthStencilView = {}; - depthStencilView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - depthStencilView.pNext = NULL; - depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - depthStencilView.format = depthFormat; - depthStencilView.flags = 0; - depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (depthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) { - depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - depthStencilView.subresourceRange.baseMipLevel = 0; - depthStencilView.subresourceRange.levelCount = 1; - depthStencilView.subresourceRange.baseArrayLayer = 0; - depthStencilView.subresourceRange.layerCount = multiviewLayerCount; - depthStencilView.image = multiviewPass.depth.image; - - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &multiviewPass.depth.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, multiviewPass.depth.image, multiviewPass.depth.memory, 0)); - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &multiviewPass.depth.view)); - } - - /* - Layered color attachment - */ - { - VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = swapChain.colorFormat; - imageCI.extent = { width, height, 1 }; - imageCI.mipLevels = 1; - imageCI.arrayLayers = multiviewLayerCount; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &multiviewPass.color.image)); - - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, multiviewPass.color.image, &memReqs); - - VkMemoryAllocateInfo memoryAllocInfo = vks::initializers::memoryAllocateInfo(); - memoryAllocInfo.allocationSize = memReqs.size; - memoryAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocInfo, nullptr, &multiviewPass.color.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, multiviewPass.color.image, multiviewPass.color.memory, 0)); - - VkImageViewCreateInfo imageViewCI = vks::initializers::imageViewCreateInfo(); - imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - imageViewCI.format = swapChain.colorFormat; - imageViewCI.flags = 0; - imageViewCI.subresourceRange = {}; - imageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageViewCI.subresourceRange.baseMipLevel = 0; - imageViewCI.subresourceRange.levelCount = 1; - imageViewCI.subresourceRange.baseArrayLayer = 0; - imageViewCI.subresourceRange.layerCount = multiviewLayerCount; - imageViewCI.image = multiviewPass.color.image; - VK_CHECK_RESULT(vkCreateImageView(device, &imageViewCI, nullptr, &multiviewPass.color.view)); - - // Create sampler to sample from the attachment in the fragment shader - VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); - samplerCI.magFilter = VK_FILTER_NEAREST; - samplerCI.minFilter = VK_FILTER_NEAREST; - samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeV = samplerCI.addressModeU; - samplerCI.addressModeW = samplerCI.addressModeU; - samplerCI.mipLodBias = 0.0f; - samplerCI.maxAnisotropy = 1.0f; - samplerCI.minLod = 0.0f; - samplerCI.maxLod = 1.0f; - samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &multiviewPass.sampler)); - - // Fill a descriptor for later use in a descriptor set - multiviewPass.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - multiviewPass.descriptor.imageView = multiviewPass.color.view; - multiviewPass.descriptor.sampler = multiviewPass.sampler; - } - - /* - Renderpass - */ - { - std::array attachments = {}; - // Color attachment - attachments[0].format = swapChain.colorFormat; - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // Depth attachment - attachments[1].format = depthFormat; - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorReference = {}; - colorReference.attachment = 0; - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthReference = {}; - depthReference.attachment = 1; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - subpassDescription.pDepthStencilAttachment = &depthReference; - - // Subpass dependencies for layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassCI{}; - renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassCI.attachmentCount = static_cast(attachments.size()); - renderPassCI.pAttachments = attachments.data(); - renderPassCI.subpassCount = 1; - renderPassCI.pSubpasses = &subpassDescription; - renderPassCI.dependencyCount = static_cast(dependencies.size()); - renderPassCI.pDependencies = dependencies.data(); - - /* - Setup multiview info for the renderpass - */ - - /* - Bit mask that specifies which view rendering is broadcast to - 0011 = Broadcast to first and second view (layer) - */ - const uint32_t viewMask = 0b00000011; - - /* - Bit mask that specifies correlation between views - An implementation may use this for optimizations (concurrent render) - */ - const uint32_t correlationMask = 0b00000011; - - VkRenderPassMultiviewCreateInfo renderPassMultiviewCI{}; - renderPassMultiviewCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO; - renderPassMultiviewCI.subpassCount = 1; - renderPassMultiviewCI.pViewMasks = &viewMask; - renderPassMultiviewCI.correlationMaskCount = 1; - renderPassMultiviewCI.pCorrelationMasks = &correlationMask; - - renderPassCI.pNext = &renderPassMultiviewCI; - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &multiviewPass.renderPass)); - } - - /* - Framebuffer - */ - { - VkImageView attachments[2]; - attachments[0] = multiviewPass.color.view; - attachments[1] = multiviewPass.depth.view; - - VkFramebufferCreateInfo framebufferCI = vks::initializers::framebufferCreateInfo(); - framebufferCI.renderPass = multiviewPass.renderPass; - framebufferCI.attachmentCount = 2; - framebufferCI.pAttachments = attachments; - framebufferCI.width = width; - framebufferCI.height = height; - framebufferCI.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &framebufferCI, nullptr, &multiviewPass.frameBuffer)); - } - } - - void buildCommandBuffers() - { - if (resized) - return; - - /* - View display - */ - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - VkViewport viewport = vks::initializers::viewport((float)width / 2.0f, (float)height, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(width / 2, height, 0, 0); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - // Left eye - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, viewDisplayPipelines[0]); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - // Right eye - viewport.x = (float)width / 2; - scissor.offset.x = width / 2; - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, viewDisplayPipelines[1]); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - /* - Multiview layered attachment scene rendering - */ - - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = multiviewPass.renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < multiviewPass.commandBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = multiviewPass.frameBuffer; - - VK_CHECK_RESULT(vkBeginCommandBuffer(multiviewPass.commandBuffers[i], &cmdBufInfo)); - vkCmdBeginRenderPass(multiviewPass.commandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(multiviewPass.commandBuffers[i], 0, 1, &viewport); - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(multiviewPass.commandBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(multiviewPass.commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(multiviewPass.commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - scene.draw(multiviewPass.commandBuffers[i]); - - vkCmdEndRenderPass(multiviewPass.commandBuffers[i]); - VK_CHECK_RESULT(vkEndCommandBuffer(multiviewPass.commandBuffers[i])); - } - } - } - - void loadAssets() - { - scene.loadFromFile(getAssetPath() + "models/sampleroom.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY); - } - - void prepareDescriptors() - { - /* - Pool - */ - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - /* - Layouts - */ - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - /* - Descriptors - */ - VkDescriptorSetAllocateInfo allocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocateInfo, &descriptorSet)); - updateDescriptors(); - } - - void updateDescriptors() - { - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &multiviewPass.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - - VkSemaphoreCreateInfo semaphoreCI = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &multiviewPass.semaphore)); - - /* - Display multi view features and properties - */ - - VkPhysicalDeviceFeatures2KHR deviceFeatures2{}; - VkPhysicalDeviceMultiviewFeaturesKHR extFeatures{}; - extFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR; - deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; - deviceFeatures2.pNext = &extFeatures; - PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR")); - vkGetPhysicalDeviceFeatures2KHR(physicalDevice, &deviceFeatures2); - std::cout << "Multiview features:" << std::endl; - std::cout << "\tmultiview = " << extFeatures.multiview << std::endl; - std::cout << "\tmultiviewGeometryShader = " << extFeatures.multiviewGeometryShader << std::endl; - std::cout << "\tmultiviewTessellationShader = " << extFeatures.multiviewTessellationShader << std::endl; - std::cout << std::endl; - - VkPhysicalDeviceProperties2KHR deviceProps2{}; - VkPhysicalDeviceMultiviewPropertiesKHR extProps{}; - extProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR; - deviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; - deviceProps2.pNext = &extProps; - PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR")); - vkGetPhysicalDeviceProperties2KHR(physicalDevice, &deviceProps2); - std::cout << "Multiview properties:" << std::endl; - std::cout << "\tmaxMultiviewViewCount = " << extProps.maxMultiviewViewCount << std::endl; - std::cout << "\tmaxMultiviewInstanceIndex = " << extProps.maxMultiviewInstanceIndex << std::endl; - - /* - Create graphics pipeline - */ - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, multiviewPass.renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); - - /* - Load shaders - Contrary to the viewport array example we don't need a geometry shader for broadcasting - */ - std::array shaderStages; - shaderStages[0] = loadShader(getShadersPath() + "multiview/multiview.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "multiview/multiview.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - pipelineCI.stageCount = 2; - pipelineCI.pStages = shaderStages.data(); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - - /* - Full screen pass - */ - - float multiviewArrayLayer = 0.0f; - - VkSpecializationMapEntry specializationMapEntry{ 0, 0, sizeof(float) }; - - VkSpecializationInfo specializationInfo{}; - specializationInfo.dataSize = sizeof(float); - specializationInfo.mapEntryCount = 1; - specializationInfo.pMapEntries = &specializationMapEntry; - specializationInfo.pData = &multiviewArrayLayer; - - rasterizationStateCI.cullMode = VK_CULL_MODE_FRONT_BIT; - - /* - Separate pipelines per eye (view) using specialization constants to set view array layer to sample from - */ - for (uint32_t i = 0; i < 2; i++) { - shaderStages[0] = loadShader(getShadersPath() + "multiview/viewdisplay.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "multiview/viewdisplay.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - shaderStages[1].pSpecializationInfo = &specializationInfo; - multiviewArrayLayer = (float)i; - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCI.pVertexInputState = &emptyInputState; - pipelineCI.layout = pipelineLayout; - pipelineCI.renderPass = renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &viewDisplayPipelines[i])); - } - - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - // Matrices for the two viewports - // See http://paulbourke.net/stereographics/stereorender/ - - // Calculate some variables - float aspectRatio = (float)(width * 0.5f) / (float)height; - float wd2 = zNear * tan(glm::radians(fov / 2.0f)); - float ndfl = zNear / focalLength; - float left, right; - float top = wd2; - float bottom = -wd2; - - glm::vec3 camFront; - camFront.x = -cos(glm::radians(camera.rotation.x)) * sin(glm::radians(camera.rotation.y)); - camFront.y = sin(glm::radians(camera.rotation.x)); - camFront.z = cos(glm::radians(camera.rotation.x)) * cos(glm::radians(camera.rotation.y)); - camFront = glm::normalize(camFront); - glm::vec3 camRight = glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))); - - glm::mat4 rotM = glm::mat4(1.0f); - glm::mat4 transM; - - rotM = glm::rotate(rotM, glm::radians(camera.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); - rotM = glm::rotate(rotM, glm::radians(camera.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - rotM = glm::rotate(rotM, glm::radians(camera.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); - - // Left eye - left = -aspectRatio * wd2 - 0.5f * eyeSeparation * ndfl; - right = aspectRatio * wd2 - 0.5f * eyeSeparation * ndfl; - - transM = glm::translate(glm::mat4(1.0f), camera.position - camRight * (eyeSeparation / 2.0f)); - - uniformData.projection[0] = glm::frustum(left, right, bottom, top, zNear, zFar); - uniformData.modelview[0] = rotM * transM; - - // Right eye - left = -aspectRatio * wd2 + 0.5f * eyeSeparation * ndfl; - right = aspectRatio * wd2 + 0.5f * eyeSeparation * ndfl; - - transM = glm::translate(glm::mat4(1.0f), camera.position + camRight * (eyeSeparation / 2.0f)); - - uniformData.projection[1] = glm::frustum(left, right, bottom, top, zNear, zFar); - uniformData.modelview[1] = rotM * transM; - - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareMultiview(); - prepareUniformBuffers(); - prepareDescriptors(); - preparePipelines(); - - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast(drawCmdBuffers.size())); - multiviewPass.commandBuffers.resize(drawCmdBuffers.size()); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, multiviewPass.commandBuffers.data())); - - buildCommandBuffers(); - - VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); - multiviewPass.waitFences.resize(multiviewPass.commandBuffers.size()); - for (auto& fence : multiviewPass.waitFences) { - VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); - } - - prepared = true; - } - - // SRS - Recreate and update Multiview resources when window size has changed - virtual void windowResized() - { - vkDestroyImageView(device, multiviewPass.color.view, nullptr); - vkDestroyImage(device, multiviewPass.color.image, nullptr); - vkFreeMemory(device, multiviewPass.color.memory, nullptr); - vkDestroyImageView(device, multiviewPass.depth.view, nullptr); - vkDestroyImage(device, multiviewPass.depth.image, nullptr); - vkFreeMemory(device, multiviewPass.depth.memory, nullptr); - - vkDestroyRenderPass(device, multiviewPass.renderPass, nullptr); - vkDestroySampler(device, multiviewPass.sampler, nullptr); - vkDestroyFramebuffer(device, multiviewPass.frameBuffer, nullptr); - - prepareMultiview(); - updateDescriptors(); - - // SRS - Recreate Multiview command buffers in case number of swapchain images has changed on resize - vkFreeCommandBuffers(device, cmdPool, static_cast(multiviewPass.commandBuffers.size()), multiviewPass.commandBuffers.data()); - - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast(drawCmdBuffers.size())); - multiviewPass.commandBuffers.resize(drawCmdBuffers.size()); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, multiviewPass.commandBuffers.data())); - - resized = false; - buildCommandBuffers(); - - // SRS - Recreate Multiview fences in case number of swapchain images has changed on resize - for (auto& fence : multiviewPass.waitFences) { - vkDestroyFence(device, fence, nullptr); - } - - VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); - multiviewPass.waitFences.resize(multiviewPass.commandBuffers.size()); - for (auto& fence : multiviewPass.waitFences) { - VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); - } - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - - // Multiview offscreen render - VK_CHECK_RESULT(vkWaitForFences(device, 1, &multiviewPass.waitFences[currentBuffer], VK_TRUE, UINT64_MAX)); - VK_CHECK_RESULT(vkResetFences(device, 1, &multiviewPass.waitFences[currentBuffer])); - submitInfo.pWaitSemaphores = &semaphores.presentComplete; - submitInfo.pSignalSemaphores = &multiviewPass.semaphore; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &multiviewPass.commandBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, multiviewPass.waitFences[currentBuffer])); - - // View display - VK_CHECK_RESULT(vkWaitForFences(device, 1, &waitFences[currentBuffer], VK_TRUE, UINT64_MAX)); - VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[currentBuffer])); - submitInfo.pWaitSemaphores = &multiviewPass.semaphore; - submitInfo.pSignalSemaphores = &semaphores.renderComplete; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, waitFences[currentBuffer])); - - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->sliderFloat("Eye separation", &eyeSeparation, -1.0f, 1.0f)) { - updateUniformBuffers(); - } - if (overlay->sliderFloat("Barrel distortion", &uniformData.distortionAlpha, -0.6f, 0.6f)) { - updateUniformBuffers(); - } - } - } - -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/negativeviewportheight/negativeviewportheight.cpp b/examples/negativeviewportheight/negativeviewportheight.cpp deleted file mode 100644 index 473c4eb1..00000000 --- a/examples/negativeviewportheight/negativeviewportheight.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* -* Vulkan Example - Using negative viewport heights for changing Vulkan's coordinate system -* -* Note: Requires a device that supports VK_KHR_MAINTENANCE1 -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool negativeViewport = true; - float offsety = 0.0f; - float offsetx = 0.0f; - int32_t windingOrder = 1; - int32_t cullMode = (int32_t)VK_CULL_MODE_BACK_BIT; - int32_t quadType = 0; - - VkPipelineLayout pipelineLayout; - VkPipeline pipeline = VK_NULL_HANDLE; - VkDescriptorSetLayout descriptorSetLayout; - struct DescriptorSets { - VkDescriptorSet CW; - VkDescriptorSet CCW; - } descriptorSets; - - struct Textures { - vks::Texture2D CW; - vks::Texture2D CCW; - } textures; - - struct Quad { - vks::Buffer verticesYUp; - vks::Buffer verticesYDown; - vks::Buffer indicesCCW; - vks::Buffer indicesCW; - void destroy() - { - verticesYUp.destroy(); - verticesYDown.destroy(); - indicesCCW.destroy(); - indicesCW.destroy(); - } - } quad; - - VulkanExample() : VulkanExampleBase() - { - title = "Negative Viewport height"; - // [POI] VK_KHR_MAINTENANCE1 is required for using negative viewport heights - // Note: This is core as of Vulkan 1.1. So if you target 1.1 you don't have to explicitly enable this - enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); - } - - ~VulkanExample() - { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - textures.CW.destroy(); - textures.CCW.destroy(); - quad.destroy(); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - // [POI] Viewport setup - VkViewport viewport{}; - if (negativeViewport) { - viewport.x = offsetx; - // [POI] When using a negative viewport height, the origin needs to be adjusted too - viewport.y = (float)height - offsety; - viewport.width = (float)width; - // [POI] Flip the sign of the viewport's height - viewport.height = -(float)height; - } - else { - viewport.x = offsetx; - viewport.y = offsety; - viewport.width = (float)width; - viewport.height = (float)height; - } - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - - // Render the quad with clock wise and counter clock wise indices, visibility is determined by pipeline settings - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.CW, 0, nullptr); - vkCmdBindIndexBuffer(drawCmdBuffers[i], quad.indicesCW.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, quadType == 0 ? &quad.verticesYDown.buffer : &quad.verticesYUp.buffer, offsets); - vkCmdDrawIndexed(drawCmdBuffers[i], 6, 1, 0, 0, 0); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.CCW, 0, nullptr); - vkCmdBindIndexBuffer(drawCmdBuffers[i], quad.indicesCCW.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(drawCmdBuffers[i], 6, 1, 0, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - textures.CW.loadFromFile(getAssetPath() + "textures/texture_orientation_cw_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.CCW.loadFromFile(getAssetPath() + "textures/texture_orientation_ccw_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - - // [POI] Create two quads with different Y orientations - - struct Vertex { - float pos[3]; - float uv[2]; - }; - - const float ar = (float)height / (float)width; - - // OpenGL style (y points upwards) - std::vector verticesYPos = { - { -1.0f * ar, 1.0f, 1.0f, 0.0f, 1.0f }, - { -1.0f * ar, -1.0f, 1.0f, 0.0f, 0.0f }, - { 1.0f * ar, -1.0f, 1.0f, 1.0f, 0.0f }, - { 1.0f * ar, 1.0f, 1.0f, 1.0f, 1.0f }, - }; - - // Vulkan style (y points downwards) - std::vector verticesYNeg = { - { -1.0f * ar, -1.0f, 1.0f, 0.0f, 1.0f }, - { -1.0f * ar, 1.0f, 1.0f, 0.0f, 0.0f }, - { 1.0f * ar, 1.0f, 1.0f, 1.0f, 0.0f }, - { 1.0f * ar, -1.0f, 1.0f, 1.0f, 1.0f }, - }; - - const VkMemoryPropertyFlags memoryPropertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, memoryPropertyFlags, &quad.verticesYUp, sizeof(Vertex) * 4, verticesYPos.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, memoryPropertyFlags, &quad.verticesYDown, sizeof(Vertex) * 4, verticesYNeg.data())); - - // [POI] Create two set of indices, one for counter clock wise, and one for clock wise rendering - std::vector indices = { 2,1,0, 0,3,2 }; - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, memoryPropertyFlags, &quad.indicesCCW, indices.size() * sizeof(uint32_t), indices.data())); - indices = { 0,1,2, 2,3,0 }; - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, memoryPropertyFlags, &quad.indicesCW, indices.size() * sizeof(uint32_t), indices.data())); - } - - void setupDescriptors() - { - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayout)); - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - VkDescriptorPoolSize poolSize = vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2); - VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(1, &poolSize, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorPool)); - - VkDescriptorSetAllocateInfo descriptorSetAI = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAI, &descriptorSets.CW)); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAI, &descriptorSets.CCW)); - - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.CW, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &textures.CW.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.CCW, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &textures.CCW.descriptor) - }; - vkUpdateDescriptorSets(device, 2, &writeDescriptorSets[0], 0, nullptr); - } - - void preparePipelines() - { - if (pipeline != VK_NULL_HANDLE) { - vkDestroyPipeline(device, pipeline, nullptr); - } - - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); - - VkPipelineRasterizationStateCreateInfo rasterizationStateCI{}; - rasterizationStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizationStateCI.polygonMode = VK_POLYGON_MODE_FILL; - rasterizationStateCI.lineWidth = 1.0f; - rasterizationStateCI.cullMode = VK_CULL_MODE_NONE + cullMode; - rasterizationStateCI.frontFace = windingOrder == 0 ? VK_FRONT_FACE_CLOCKWISE : VK_FRONT_FACE_COUNTER_CLOCKWISE; - - // Vertex bindings and attributes - std::vector vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(float) * 5, VK_VERTEX_INPUT_RATE_VERTEX), - }; - std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32_SFLOAT, sizeof(float) * 3), // uv - }; - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - VkGraphicsPipelineCreateInfo pipelineCreateInfoCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - //pipelineCreateInfoCI.pVertexInputState = &emptyInputState; - pipelineCreateInfoCI.pVertexInputState = &vertexInputState; - pipelineCreateInfoCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCreateInfoCI.pRasterizationState = &rasterizationStateCI; - pipelineCreateInfoCI.pColorBlendState = &colorBlendStateCI; - pipelineCreateInfoCI.pMultisampleState = &multisampleStateCI; - pipelineCreateInfoCI.pViewportState = &viewportStateCI; - pipelineCreateInfoCI.pDepthStencilState = &depthStencilStateCI; - pipelineCreateInfoCI.pDynamicState = &dynamicStateCI; - - const std::array shaderStages = { - loadShader(getShadersPath() + "negativeviewportheight/quad.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "negativeviewportheight/quad.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - - pipelineCreateInfoCI.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfoCI.pStages = shaderStages.data(); - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfoCI, nullptr, &pipeline)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Scene")) { - overlay->text("Quad type"); - if (overlay->comboBox("##quadtype", &quadType, { "VK (y negative)", "GL (y positive)" })) { - buildCommandBuffers(); - } - } - - if (overlay->header("Viewport")) { - if (overlay->checkBox("Negative viewport height", &negativeViewport)) { - buildCommandBuffers(); - } - if (overlay->sliderFloat("offset x", &offsetx, -(float)width, (float)width)) { - buildCommandBuffers(); - } - if (overlay->sliderFloat("offset y", &offsety, -(float)height, (float)height)) { - buildCommandBuffers(); - } - } - if (overlay->header("Pipeline")) { - overlay->text("Winding order"); - if (overlay->comboBox("##windingorder", &windingOrder, { "clock wise", "counter clock wise" })) { - preparePipelines(); - } - overlay->text("Cull mode"); - if (overlay->comboBox("##cullmode", &cullMode, { "none", "front face", "back face" })) { - preparePipelines(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/occlusionquery/occlusionquery.cpp b/examples/occlusionquery/occlusionquery.cpp deleted file mode 100644 index ca502213..00000000 --- a/examples/occlusionquery/occlusionquery.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/* -* Vulkan Example - Using occlusion query for visibility testing -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - - struct { - vkglTF::Model teapot; - vkglTF::Model plane; - vkglTF::Model sphere; - } models; - - struct { - vks::Buffer occluder; - vks::Buffer teapot; - vks::Buffer sphere; - } uniformBuffers; - - struct UBOVS { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - glm::vec4 color = glm::vec4(0.0f); - glm::vec4 lightPos = glm::vec4(10.0f, -10.0f, 10.0f, 1.0f); - float visible; - } uboVS; - - struct { - VkPipeline solid; - VkPipeline occluder; - // Pipeline with basic shaders used for occlusion pass - VkPipeline simple; - } pipelines; - - struct { - VkDescriptorSet teapot; - VkDescriptorSet sphere; - } descriptorSets; - - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; - - // Pool that stores all occlusion queries - VkQueryPool queryPool; - - // Passed query samples - uint64_t passedSamples[2] = { 1,1 }; - - VulkanExample() : VulkanExampleBase() - { - title = "Occlusion queries"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -7.5f)); - camera.setRotation(glm::vec3(0.0f, -123.75f, 0.0f)); - camera.setRotationSpeed(0.5f); - camera.setPerspective(60.0f, (float)width / (float)height, 1.0f, 256.0f); - } - - ~VulkanExample() - { - // Clean up used Vulkan resources - // Note : Inherited destructor cleans up resources stored in base class - vkDestroyPipeline(device, pipelines.solid, nullptr); - vkDestroyPipeline(device, pipelines.occluder, nullptr); - vkDestroyPipeline(device, pipelines.simple, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - vkDestroyQueryPool(device, queryPool, nullptr); - - uniformBuffers.occluder.destroy(); - uniformBuffers.sphere.destroy(); - uniformBuffers.teapot.destroy(); - } - - // Create a query pool for storing the occlusion query result - void setupQueryPool() - { - VkQueryPoolCreateInfo queryPoolInfo = {}; - queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - queryPoolInfo.queryType = VK_QUERY_TYPE_OCCLUSION; - queryPoolInfo.queryCount = 2; - VK_CHECK_RESULT(vkCreateQueryPool(device, &queryPoolInfo, NULL, &queryPool)); - } - - // Retrieves the results of the occlusion queries submitted to the command buffer - void getQueryResults() - { - // We use vkGetQueryResults to copy the results into a host visible buffer - vkGetQueryPoolResults( - device, - queryPool, - 0, - 2, - sizeof(passedSamples), - passedSamples, - sizeof(uint64_t), - // Store results a 64 bit values and wait until the results have been finished - // If you don't want to wait, you can use VK_QUERY_RESULT_WITH_AVAILABILITY_BIT - // which also returns the state of the result (ready) in the result - VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Reset query pool - // Must be done outside of render pass - vkCmdResetQueryPool(drawCmdBuffers[i], queryPool, 0, 2); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport( - (float)width, - (float)height, - 0.0f, - 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D( - width, - height, - 0, - 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - glm::mat4 modelMatrix = glm::mat4(1.0f); - - // Occlusion pass - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.simple); - - // Occluder first - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - models.plane.draw(drawCmdBuffers[i]); - - // Teapot - vkCmdBeginQuery(drawCmdBuffers[i], queryPool, 0, VK_FLAGS_NONE); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.teapot, 0, NULL); - models.teapot.draw(drawCmdBuffers[i]); - vkCmdEndQuery(drawCmdBuffers[i], queryPool, 0); - - // Sphere - vkCmdBeginQuery(drawCmdBuffers[i], queryPool, 1, VK_FLAGS_NONE); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.sphere, 0, NULL); - models.sphere.draw(drawCmdBuffers[i]); - vkCmdEndQuery(drawCmdBuffers[i], queryPool, 1); - - // Visible pass - // Clear color and depth attachments - VkClearAttachment clearAttachments[2] = {}; - - clearAttachments[0].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - clearAttachments[0].clearValue.color = defaultClearColor; - clearAttachments[0].colorAttachment = 0; - - clearAttachments[1].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - clearAttachments[1].clearValue.depthStencil = { 1.0f, 0 }; - - VkClearRect clearRect = {}; - clearRect.layerCount = 1; - clearRect.rect.offset = { 0, 0 }; - clearRect.rect.extent = { width, height }; - - vkCmdClearAttachments( - drawCmdBuffers[i], - 2, - clearAttachments, - 1, - &clearRect); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solid); - - // Teapot - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.teapot, 0, NULL); - models.teapot.draw(drawCmdBuffers[i]); - - // Sphere - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.sphere, 0, NULL); - models.sphere.draw(drawCmdBuffers[i]); - - // Occluder - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.occluder); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - models.plane.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.plane.loadFromFile(getAssetPath() + "models/plane_z.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.teapot.loadFromFile(getAssetPath() + "models/teapot.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.sphere.loadFromFile(getAssetPath() + "models/sphere.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - // One uniform buffer block for each mesh - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - // Occluder (plane) - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.occluder.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - // Teapot - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.teapot)); - writeDescriptorSets[0].dstSet = descriptorSets.teapot; - writeDescriptorSets[0].pBufferInfo = &uniformBuffers.teapot.descriptor; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - // Sphere - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.sphere)); - writeDescriptorSets[0].dstSet = descriptorSets.sphere; - writeDescriptorSets[0].pBufferInfo = &uniformBuffers.sphere.descriptor; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color });; - - // Solid rendering pipeline - shaderStages[0] = loadShader(getShadersPath() + "occlusionquery/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "occlusionquery/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.solid)); - - // Basic pipeline for coloring occluded objects - shaderStages[0] = loadShader(getShadersPath() + "occlusionquery/simple.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "occlusionquery/simple.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - rasterizationState.cullMode = VK_CULL_MODE_NONE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.simple)); - - // Visual pipeline for the occluder - shaderStages[0] = loadShader(getShadersPath() + "occlusionquery/occluder.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "occlusionquery/occluder.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Enable blending - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.occluder)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.occluder, - sizeof(uboVS))); - - // Teapot - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.teapot, - sizeof(uboVS))); - - // Sphere - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.sphere, - sizeof(uboVS))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffers.occluder.map()); - VK_CHECK_RESULT(uniformBuffers.teapot.map()); - VK_CHECK_RESULT(uniformBuffers.sphere.map()); - - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - uboVS.projection = camera.matrices.perspective; - uboVS.view = camera.matrices.view; - - // Occluder - uboVS.visible = 1.0f; - uboVS.model = glm::scale(glm::mat4(1.0f), glm::vec3(6.0f)); - uboVS.color = glm::vec4(0.0f, 0.0f, 1.0f, 0.5f); - memcpy(uniformBuffers.occluder.mapped, &uboVS, sizeof(uboVS)); - - // Teapot - // Toggle color depending on visibility - uboVS.visible = (passedSamples[0] > 0) ? 1.0f : 0.0f; - uboVS.model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3.0f)); - uboVS.color = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f); - memcpy(uniformBuffers.teapot.mapped, &uboVS, sizeof(uboVS)); - - // Sphere - // Toggle color depending on visibility - uboVS.visible = (passedSamples[1] > 0) ? 1.0f : 0.0f; - uboVS.model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 3.0f)); - uboVS.color = glm::vec4(0.0f, 1.0f, 0.0f, 1.0f); - memcpy(uniformBuffers.sphere.mapped, &uboVS, sizeof(uboVS)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - setupQueryPool(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - updateUniformBuffers(); - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - // Read query results for displaying in next frame - getQueryResults(); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Occlusion query results")) { - overlay->text("Teapot: %d samples passed", passedSamples[0]); - overlay->text("Sphere: %d samples passed", passedSamples[1]); - } - } - -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/offscreen/offscreen.cpp b/examples/offscreen/offscreen.cpp deleted file mode 100644 index 93dc8ff9..00000000 --- a/examples/offscreen/offscreen.cpp +++ /dev/null @@ -1,620 +0,0 @@ -/* -* Vulkan Example - Offscreen rendering using a separate framebuffer -* -* Copyright (C) 2016-2024 Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -// Offscreen frame buffer properties -#define FB_DIM 512 -#define FB_COLOR_FORMAT VK_FORMAT_R8G8B8A8_UNORM - -class VulkanExample : public VulkanExampleBase -{ -public: - bool debugDisplay = false; - - struct { - vkglTF::Model example; - vkglTF::Model plane; - } models; - - struct { - vks::Buffer vsShared; - vks::Buffer vsMirror; - vks::Buffer vsOffScreen; - } uniformBuffers; - - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - glm::vec4 lightPos = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); - } uniformData; - - struct { - VkPipeline debug{ VK_NULL_HANDLE }; - VkPipeline shaded{ VK_NULL_HANDLE }; - VkPipeline shadedOffscreen{ VK_NULL_HANDLE }; - VkPipeline mirror{ VK_NULL_HANDLE }; - } pipelines; - - struct { - VkPipelineLayout textured{ VK_NULL_HANDLE }; - VkPipelineLayout shaded{ VK_NULL_HANDLE }; - } pipelineLayouts; - - struct { - VkDescriptorSet offscreen{ VK_NULL_HANDLE }; - VkDescriptorSet mirror{ VK_NULL_HANDLE }; - VkDescriptorSet model{ VK_NULL_HANDLE }; - } descriptorSets; - - struct { - VkDescriptorSetLayout textured{ VK_NULL_HANDLE }; - VkDescriptorSetLayout shaded{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - // Framebuffer for offscreen rendering - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory mem; - VkImageView view; - }; - struct OffscreenPass { - int32_t width, height; - VkFramebuffer frameBuffer; - FrameBufferAttachment color, depth; - VkRenderPass renderPass; - VkSampler sampler; - VkDescriptorImageInfo descriptor; - } offscreenPass{}; - - glm::vec3 modelPosition = glm::vec3(0.0f, -1.0f, 0.0f); - glm::vec3 modelRotation = glm::vec3(0.0f); - - VulkanExample() : VulkanExampleBase() - { - title = "Offscreen rendering"; - timerSpeed *= 0.25f; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 1.0f, -6.0f)); - camera.setRotation(glm::vec3(-2.5f, 0.0f, 0.0f)); - camera.setRotationSpeed(0.5f); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - // The scene shader uses a clipping plane, so this feature has to be enabled - enabledFeatures.shaderClipDistance = VK_TRUE; - } - - ~VulkanExample() - { - if (device) { - // Frame buffer - - // Color attachment - vkDestroyImageView(device, offscreenPass.color.view, nullptr); - vkDestroyImage(device, offscreenPass.color.image, nullptr); - vkFreeMemory(device, offscreenPass.color.mem, nullptr); - - // Depth attachment - vkDestroyImageView(device, offscreenPass.depth.view, nullptr); - vkDestroyImage(device, offscreenPass.depth.image, nullptr); - vkFreeMemory(device, offscreenPass.depth.mem, nullptr); - - vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); - vkDestroySampler(device, offscreenPass.sampler, nullptr); - vkDestroyFramebuffer(device, offscreenPass.frameBuffer, nullptr); - - vkDestroyPipeline(device, pipelines.debug, nullptr); - vkDestroyPipeline(device, pipelines.shaded, nullptr); - vkDestroyPipeline(device, pipelines.shadedOffscreen, nullptr); - vkDestroyPipeline(device, pipelines.mirror, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayouts.textured, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.shaded, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.shaded, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textured, nullptr); - - // Uniform buffers - uniformBuffers.vsShared.destroy(); - uniformBuffers.vsMirror.destroy(); - uniformBuffers.vsOffScreen.destroy(); - } - } - - // Setup the offscreen framebuffer for rendering the mirrored scene - // The color attachment of this framebuffer will then be used to sample from in the fragment shader of the final pass - void prepareOffscreen() - { - offscreenPass.width = FB_DIM; - offscreenPass.height = FB_DIM; - - // Find a suitable depth format - VkFormat fbDepthFormat; - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat); - assert(validDepthFormat); - - // Color attachment - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = FB_COLOR_FORMAT; - image.extent.width = offscreenPass.width; - image.extent.height = offscreenPass.height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - // We will sample directly from the color attachment - image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.color.image)); - vkGetImageMemoryRequirements(device, offscreenPass.color.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.color.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.color.image, offscreenPass.color.mem, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = FB_COLOR_FORMAT; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = offscreenPass.color.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreenPass.color.view)); - - // Create sampler to sample from the attachment in the fragment shader - VkSamplerCreateInfo samplerInfo = vks::initializers::samplerCreateInfo(); - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = samplerInfo.addressModeU; - samplerInfo.addressModeW = samplerInfo.addressModeU; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.maxAnisotropy = 1.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 1.0f; - samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &offscreenPass.sampler)); - - // Depth stencil attachment - image.format = fbDepthFormat; - image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.depth.image)); - vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0)); - - VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo(); - depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilView.format = fbDepthFormat; - depthStencilView.flags = 0; - depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (fbDepthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) { - depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - depthStencilView.subresourceRange.baseMipLevel = 0; - depthStencilView.subresourceRange.levelCount = 1; - depthStencilView.subresourceRange.baseArrayLayer = 0; - depthStencilView.subresourceRange.layerCount = 1; - depthStencilView.image = offscreenPass.depth.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view)); - - // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering - - std::array attchmentDescriptions = {}; - // Color attachment - attchmentDescriptions[0].format = FB_COLOR_FORMAT; - attchmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attchmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // Depth attachment - attchmentDescriptions[1].format = fbDepthFormat; - attchmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - VkAttachmentReference depthReference = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - subpassDescription.pDepthStencilAttachment = &depthReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_NONE_KHR; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Create the actual renderpass - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attchmentDescriptions.size()); - renderPassInfo.pAttachments = attchmentDescriptions.data(); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpassDescription; - renderPassInfo.dependencyCount = static_cast(dependencies.size()); - renderPassInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &offscreenPass.renderPass)); - - VkImageView attachments[2]; - attachments[0] = offscreenPass.color.view; - attachments[1] = offscreenPass.depth.view; - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = offscreenPass.renderPass; - fbufCreateInfo.attachmentCount = 2; - fbufCreateInfo.pAttachments = attachments; - fbufCreateInfo.width = offscreenPass.width; - fbufCreateInfo.height = offscreenPass.height; - fbufCreateInfo.layers = 1; - - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreenPass.frameBuffer)); - - // Fill a descriptor for later use in a descriptor set - offscreenPass.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - offscreenPass.descriptor.imageView = offscreenPass.color.view; - offscreenPass.descriptor.sampler = offscreenPass.sampler; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - First render pass: Offscreen rendering - */ - { - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = offscreenPass.renderPass; - renderPassBeginInfo.framebuffer = offscreenPass.frameBuffer; - renderPassBeginInfo.renderArea.extent.width = offscreenPass.width; - renderPassBeginInfo.renderArea.extent.height = offscreenPass.height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)offscreenPass.width, (float)offscreenPass.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(offscreenPass.width, offscreenPass.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Mirrored scene - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.shaded, 0, 1, &descriptorSets.offscreen, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.shadedOffscreen); - models.example.draw(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Second render pass: Scene rendering with applied radial blur - */ - { - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - if (debugDisplay) - { - // Display the offscreen render target - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.textured, 0, 1, &descriptorSets.mirror, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.debug); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - } else { - // Render the scene - // Reflection plane - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.textured, 0, 1, &descriptorSets.mirror, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.mirror); - models.plane.draw(drawCmdBuffers[i]); - // Model - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.shaded, 0, 1, &descriptorSets.model, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.shaded); - models.example.draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.plane.loadFromFile(getAssetPath() + "models/plane.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.example.loadFromFile(getAssetPath() + "models/chinesedragon.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 6), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 8) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 5); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings; - VkDescriptorSetLayoutCreateInfo descriptorLayoutInfo; - - // Shaded layout - setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - }; - descriptorLayoutInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutInfo, nullptr, &descriptorSetLayouts.shaded)); - - // Textured layouts - setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - descriptorLayoutInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutInfo, nullptr, &descriptorSetLayouts.textured)); - - // Sets - // Mirror plane descriptor set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textured, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.mirror)); - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.mirror, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.vsMirror.descriptor), - // Binding 1 : Fragment shader texture sampler - vks::initializers::writeDescriptorSet(descriptorSets.mirror, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &offscreenPass.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Shaded descriptor sets - allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.shaded, 1); - // Model - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.model)); - std::vector modelWriteDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.model, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.vsShared.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(modelWriteDescriptorSets.size()), modelWriteDescriptorSets.data(), 0, nullptr); - - // Offscreen - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.offscreen)); - std::vector offScreenWriteDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.offscreen, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.vsOffScreen.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(offScreenWriteDescriptorSets.size()), offScreenWriteDescriptorSets.data(), 0, nullptr); - - } - - void preparePipelines() - { - // Layouts - VkPipelineLayoutCreateInfo pipelineLayoutInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.shaded, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayouts.shaded)); - - pipelineLayoutInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.textured, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayouts.textured)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE,0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.textured, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal}); - - rasterizationState.cullMode = VK_CULL_MODE_NONE; - - // Render-target debug display - shaderStages[0] = loadShader(getShadersPath() + "offscreen/quad.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "offscreen/quad.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.debug)); - - // Mirror - shaderStages[0] = loadShader(getShadersPath() + "offscreen/mirror.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "offscreen/mirror.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.mirror)); - - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - - // Phong shading pipelines - pipelineCI.layout = pipelineLayouts.shaded; - // Scene - shaderStages[0] = loadShader(getShadersPath() + "offscreen/phong.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "offscreen/phong.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.shaded)); - // Offscreen - // Flip cull mode - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - pipelineCI.renderPass = offscreenPass.renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.shadedOffscreen)); - - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Mesh vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.vsShared, sizeof(UniformData))); - // Mirror plane vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.vsMirror, sizeof(UniformData))); - // Offscreen vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.vsOffScreen, sizeof(UniformData))); - // Map persistent - VK_CHECK_RESULT(uniformBuffers.vsShared.map()); - VK_CHECK_RESULT(uniformBuffers.vsMirror.map()); - VK_CHECK_RESULT(uniformBuffers.vsOffScreen.map()); - - updateUniformBuffers(); - updateUniformBufferOffscreen(); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - - // Model - uniformData.model = glm::mat4(1.0f); - uniformData.model = glm::rotate(uniformData.model, glm::radians(modelRotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - uniformData.model = glm::translate(uniformData.model, modelPosition); - memcpy(uniformBuffers.vsShared.mapped, &uniformData, sizeof(UniformData)); - - // Mirror - uniformData.model = glm::mat4(1.0f); - memcpy(uniformBuffers.vsMirror.mapped, &uniformData, sizeof(UniformData)); - } - - void updateUniformBufferOffscreen() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.model = glm::mat4(1.0f); - uniformData.model = glm::rotate(uniformData.model, glm::radians(modelRotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - uniformData.model = glm::scale(uniformData.model, glm::vec3(1.0f, -1.0f, 1.0f)); - uniformData.model = glm::translate(uniformData.model, modelPosition); - memcpy(uniformBuffers.vsOffScreen.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareOffscreen(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (!paused || camera.updated) - { - if (!paused) { - modelRotation.y += frameTimer * 10.0f; - } - updateUniformBuffers(); - updateUniformBufferOffscreen(); - } - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->checkBox("Display render target", &debugDisplay)) { - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/oit/oit.cpp b/examples/oit/oit.cpp deleted file mode 100644 index 5448c19a..00000000 --- a/examples/oit/oit.cpp +++ /dev/null @@ -1,592 +0,0 @@ -/* -* Vulkan Example - Order Independent Transparency rendering using linked lists -* -* Copyright by Sascha Willems - www.saschawillems.de -* Copyright by Daemyung Jang - dm86.jang@gmail.com -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -#define NODE_COUNT 20 - -class VulkanExample : public VulkanExampleBase -{ -public: - struct { - vkglTF::Model sphere; - vkglTF::Model cube; - } models; - - struct Node { - glm::vec4 color; - float depth{ 0.0f }; - uint32_t next{ 0 }; - }; - - struct { - uint32_t count{ 0 }; - uint32_t maxNodeCount{ 0 }; - } geometrySBO; - - struct GeometryPass { - VkRenderPass renderPass{ VK_NULL_HANDLE }; - VkFramebuffer framebuffer{ VK_NULL_HANDLE }; - vks::Buffer geometry; - vks::Texture headIndex; - vks::Buffer linkedList; - } geometryPass; - - struct RenderPassUniformData { - glm::mat4 projection; - glm::mat4 view; - } renderPassUniformData; - vks::Buffer renderPassUniformBuffer; - - struct ObjectData { - glm::mat4 model; - glm::vec4 color; - }; - - struct { - VkDescriptorSetLayout geometry{ VK_NULL_HANDLE }; - VkDescriptorSetLayout color{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - struct { - VkPipelineLayout geometry{ VK_NULL_HANDLE }; - VkPipelineLayout color{ VK_NULL_HANDLE }; - } pipelineLayouts; - - struct { - VkPipeline geometry{ VK_NULL_HANDLE }; - VkPipeline color{ VK_NULL_HANDLE }; - } pipelines; - - struct { - VkDescriptorSet geometry{ VK_NULL_HANDLE }; - VkDescriptorSet color{ VK_NULL_HANDLE }; - } descriptorSets; - - VkDeviceSize objectUniformBufferSize{ 0 }; - - VulkanExample() : VulkanExampleBase() - { - title = "Order independent transparency rendering"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -6.0f)); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setPerspective(60.0f, (float) width / (float) height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.geometry, nullptr); - vkDestroyPipeline(device, pipelines.color, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.geometry, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.color, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.geometry, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.color, nullptr); - destroyGeometryPass(); - renderPassUniformBuffer.destroy(); - } - } - - void getEnabledFeatures() override - { - // The linked lists are built in a fragment shader using atomic stores, so the sample won't work without that feature available - if (deviceFeatures.fragmentStoresAndAtomics) { - enabledFeatures.fragmentStoresAndAtomics = VK_TRUE; - } else { - vks::tools::exitFatal("Selected GPU does not support stores and atomic operations in the fragment stage", VK_ERROR_FEATURE_NOT_PRESENT); - } - }; - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY; - models.sphere.loadFromFile(getAssetPath() + "models/sphere.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.cube.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void prepareUniformBuffers() - { - // Create an uniform buffer for a render pass. - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &renderPassUniformBuffer, sizeof(RenderPassUniformData))); - VK_CHECK_RESULT(renderPassUniformBuffer.map()); - } - - void prepareGeometryPass() - { - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - - // Geometry render pass doesn't need any output attachment. - VkRenderPassCreateInfo renderPassInfo = vks::initializers::renderPassCreateInfo(); - renderPassInfo.attachmentCount = 0; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpassDescription; - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &geometryPass.renderPass)); - - // Geometry frame buffer doesn't need any output attachment. - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = geometryPass.renderPass; - fbufCreateInfo.attachmentCount = 0; - fbufCreateInfo.width = width; - fbufCreateInfo.height = height; - fbufCreateInfo.layers = 1; - - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &geometryPass.framebuffer)); - - // Create a buffer for GeometrySBO - vks::Buffer stagingBuffer; - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - sizeof(geometrySBO))); - VK_CHECK_RESULT(stagingBuffer.map()); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &geometryPass.geometry, - sizeof(geometrySBO))); - - // Set up GeometrySBO data. - geometrySBO.count = 0; - geometrySBO.maxNodeCount = NODE_COUNT * width * height; - memcpy(stagingBuffer.mapped, &geometrySBO, sizeof(geometrySBO)); - - // Copy data to device - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = {}; - copyRegion.size = sizeof(geometrySBO); - vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, geometryPass.geometry.buffer, 1, ©Region); - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - stagingBuffer.destroy(); - - // Create a texture for HeadIndex. - // This image will track the head index of each fragment. - geometryPass.headIndex.device = vulkanDevice; - - VkImageCreateInfo imageInfo = vks::initializers::imageCreateInfo(); - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.format = VK_FORMAT_R32_UINT; - imageInfo.extent.width = width; - imageInfo.extent.height = height; - imageInfo.extent.depth = 1; - imageInfo.mipLevels = 1; - imageInfo.arrayLayers = 1; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; -#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) - // SRS - On macOS/iOS use linear tiling for atomic image access, see https://github.com/KhronosGroup/MoltenVK/issues/1027 - imageInfo.tiling = VK_IMAGE_TILING_LINEAR; -#else - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; -#endif - imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT; - - VK_CHECK_RESULT(vkCreateImage(device, &imageInfo, nullptr, &geometryPass.headIndex.image)); - - geometryPass.headIndex.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, geometryPass.headIndex.image, &memReqs); - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &geometryPass.headIndex.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, geometryPass.headIndex.image, geometryPass.headIndex.deviceMemory, 0)); - - VkImageViewCreateInfo imageViewInfo = vks::initializers::imageViewCreateInfo(); - imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageViewInfo.format = VK_FORMAT_R32_UINT; - imageViewInfo.flags = 0; - imageViewInfo.image = geometryPass.headIndex.image; - imageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageViewInfo.subresourceRange.baseMipLevel = 0; - imageViewInfo.subresourceRange.levelCount = 1; - imageViewInfo.subresourceRange.baseArrayLayer = 0; - imageViewInfo.subresourceRange.layerCount = 1; - - VK_CHECK_RESULT(vkCreateImageView(device, &imageViewInfo, nullptr, &geometryPass.headIndex.view)); - - geometryPass.headIndex.width = width; - geometryPass.headIndex.height = height; - geometryPass.headIndex.mipLevels = 1; - geometryPass.headIndex.layerCount = 1; - geometryPass.headIndex.descriptor.imageView = geometryPass.headIndex.view; - geometryPass.headIndex.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - geometryPass.headIndex.sampler = VK_NULL_HANDLE; - - // Create a buffer for LinkedListSBO - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &geometryPass.linkedList, - sizeof(Node) * geometrySBO.maxNodeCount)); - - // Change HeadIndex image's layout from UNDEFINED to GENERAL - VkCommandBufferAllocateInfo cmdBufAllocInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - - VkCommandBuffer cmdBuf; - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocInfo, &cmdBuf)); - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - VK_CHECK_RESULT(vkBeginCommandBuffer(cmdBuf, &cmdBufInfo)); - - VkImageMemoryBarrier barrier = vks::initializers::imageMemoryBarrier(); - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - barrier.image = geometryPass.headIndex.image; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.layerCount = 1; - - vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); - - VK_CHECK_RESULT(vkEndCommandBuffer(cmdBuf)); - - VkSubmitInfo submitInfo = vks::initializers::submitInfo(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &cmdBuf; - - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VK_CHECK_RESULT(vkQueueWaitIdle(queue)); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layouts - - // Create a geometry descriptor set layout - std::vector setLayoutBindings = { - // renderPassUniformData - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // AtomicSBO - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // headIndexImage - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - // LinkedListSBO - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayouts.geometry)); - - // Create a color descriptor set layout - setLayoutBindings = { - // headIndexImage - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // LinkedListSBO - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - descriptorLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayouts.color)); - - updateDescriptors(); - } - - void updateDescriptors() - { - // Images and linked buffers are recreated on resize and part of the descriptors, so we need to update those at runtime - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.geometry, 1); - - // Update a geometry descriptor set - - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.geometry)); - - std::vector writeDescriptorSets = { - // Binding 0: renderPassUniformData - vks::initializers::writeDescriptorSet(descriptorSets.geometry, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &renderPassUniformBuffer.descriptor), - // Binding 2: GeometrySBO - vks::initializers::writeDescriptorSet(descriptorSets.geometry, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, &geometryPass.geometry.descriptor), - // Binding 3: headIndexImage - vks::initializers::writeDescriptorSet(descriptorSets.geometry, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2, &geometryPass.headIndex.descriptor), - // Binding 4: LinkedListSBO - vks::initializers::writeDescriptorSet(descriptorSets.geometry, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &geometryPass.linkedList.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Update a color descriptor set - allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.color, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.color)); - - writeDescriptorSets = { - // Binding 0: headIndexImage - vks::initializers::writeDescriptorSet(descriptorSets.color, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 0, &geometryPass.headIndex.descriptor), - // Binding 1: LinkedListSBO - vks::initializers::writeDescriptorSet(descriptorSets.color, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, &geometryPass.linkedList.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layouts - - // Create a geometry pipeline layout - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.geometry, 1); - // Static object data passed using push constants - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(ObjectData), 0); - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.geometry)); - - // Create a color pipeline layout - pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.color, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.color)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(0, nullptr); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.geometry, geometryPass.renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position }); - - // Create a geometry pipeline - shaderStages[0] = loadShader(getShadersPath() + "oit/geometry.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "oit/geometry.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.geometry)); - - // Create a color pipeline - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - - VkPipelineVertexInputStateCreateInfo vertexInputInfo = {}; - vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - - pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.color, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = &vertexInputInfo; - - shaderStages[0] = loadShader(getShadersPath() + "oit/color.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "oit/color.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - rasterizationState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.color)); - } - - void buildCommandBuffers() override - { - if (resized) - return; - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Update dynamic viewport state - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - // Update dynamic scissor state - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkClearColorValue clearColor; - clearColor.uint32[0] = 0xffffffff; - - VkImageSubresourceRange subresRange = {}; - - subresRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresRange.levelCount = 1; - subresRange.layerCount = 1; - - vkCmdClearColorImage(drawCmdBuffers[i], geometryPass.headIndex.image, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresRange); - - // Clear previous geometry pass data - vkCmdFillBuffer(drawCmdBuffers[i], geometryPass.geometry.buffer, 0, sizeof(uint32_t), 0); - - // We need a barrier to make sure all writes are finished before starting to write again - VkMemoryBarrier memoryBarrier = vks::initializers::memoryBarrier(); - memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; - vkCmdPipelineBarrier(drawCmdBuffers[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr); - - // Begin the geometry render pass - renderPassBeginInfo.renderPass = geometryPass.renderPass; - renderPassBeginInfo.framebuffer = geometryPass.framebuffer; - renderPassBeginInfo.clearValueCount = 0; - renderPassBeginInfo.pClearValues = nullptr; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.geometry); - uint32_t dynamicOffset = 0; - models.sphere.bindBuffers(drawCmdBuffers[i]); - - // Render the scene - ObjectData objectData; - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.geometry, 0, 1, &descriptorSets.geometry, 0, nullptr); - objectData.color = glm::vec4(1.0f, 0.0f, 0.0f, 0.5f); - for (int32_t x = 0; x < 5; x++) - { - for (int32_t y = 0; y < 5; y++) - { - for (int32_t z = 0; z < 5; z++) - { - glm::mat4 T = glm::translate(glm::mat4(1.0f), glm::vec3(x - 2, y - 2, z - 2)); - glm::mat4 S = glm::scale(glm::mat4(1.0f), glm::vec3(0.3f)); - objectData.model = T * S; - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayouts.geometry, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ObjectData), &objectData); - models.sphere.draw(drawCmdBuffers[i]); - } - } - } - - models.cube.bindBuffers(drawCmdBuffers[i]); - objectData.color = glm::vec4(0.0f, 0.0f, 1.0f, 0.5f); - for (uint32_t x = 0; x < 2; x++) - { - glm::mat4 T = glm::translate(glm::mat4(1.0f), glm::vec3(3.0f * x - 1.5f, 0.0f, 0.0f)); - glm::mat4 S = glm::scale(glm::mat4(1.0f), glm::vec3(0.2f)); - objectData.model = T * S; - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayouts.geometry, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ObjectData), &objectData); - models.cube.draw(drawCmdBuffers[i]); - } - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - // Make a pipeline barrier to guarantee the geometry pass is done - vkCmdPipelineBarrier(drawCmdBuffers[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 0, nullptr); - - // We need a barrier to make sure all writes are finished before starting to write again - memoryBarrier = vks::initializers::memoryBarrier(); - memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; - memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; - vkCmdPipelineBarrier(drawCmdBuffers[i], VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr); - - // Begin the color render pass - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.color); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.color, 0, 1, &descriptorSets.color, 0, nullptr); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - drawUI(drawCmdBuffers[i]); - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void updateUniformBuffers() - { - renderPassUniformData.projection = camera.matrices.perspective; - renderPassUniformData.view = camera.matrices.view; - memcpy(renderPassUniformBuffer.mapped, &renderPassUniformData, sizeof(RenderPassUniformData)); - } - - void prepare() override - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - prepareGeometryPass(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - updateUniformBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void render() override - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - void windowResized() override - { - destroyGeometryPass(); - prepareGeometryPass(); - vkResetDescriptorPool(device, descriptorPool, 0); - updateDescriptors(); - resized = false; - buildCommandBuffers(); - } - - void destroyGeometryPass() - { - vkDestroyRenderPass(device, geometryPass.renderPass, nullptr); - vkDestroyFramebuffer(device, geometryPass.framebuffer, nullptr); - geometryPass.geometry.destroy(); - geometryPass.headIndex.destroy(); - geometryPass.linkedList.destroy(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/parallaxmapping/parallaxmapping.cpp b/examples/parallaxmapping/parallaxmapping.cpp deleted file mode 100644 index 6875ea85..00000000 --- a/examples/parallaxmapping/parallaxmapping.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* -* Vulkan Example - Parallax Mapping -* -* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - struct { - vks::Texture2D colorMap; - // Normals and height are combined into one texture (height = alpha channel) - vks::Texture2D normalHeightMap; - } textures; - - vkglTF::Model plane; - - struct UniformDataVertexShader { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - glm::vec4 lightPos = glm::vec4(0.0f, -2.0f, 0.0f, 1.0f); - glm::vec4 cameraPos; - } uniformDataVertexShader; - - struct UniformDataFragmentShader { - float heightScale = 0.1f; - // Basic parallax mapping needs a bias to look any good (and is hard to tweak) - float parallaxBias = -0.02f; - // Number of layers for steep parallax and parallax occlusion (more layer = better result for less performance) - float numLayers = 48.0f; - // (Parallax) mapping mode to use - int32_t mappingMode = 4; - } uniformDataFragmentShader; - - struct { - vks::Buffer vertexShader; - vks::Buffer fragmentShader; - } uniformBuffers; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - const std::vector mappingModes = { - "Color only", - "Normal mapping", - "Parallax mapping", - "Steep parallax mapping", - "Parallax occlusion mapping", - }; - - VulkanExample() : VulkanExampleBase() - { - title = "Parallax Mapping"; - timerSpeed *= 0.5f; - camera.type = Camera::CameraType::firstperson; - camera.setPosition(glm::vec3(0.0f, 1.25f, -1.5f)); - camera.setRotation(glm::vec3(-45.0f, 0.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffers.vertexShader.destroy(); - uniformBuffers.fragmentShader.destroy(); - textures.colorMap.destroy(); - textures.normalHeightMap.destroy(); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - plane.loadFromFile(getAssetPath() + "models/plane.gltf", vulkanDevice, queue, glTFLoadingFlags); - textures.normalHeightMap.loadFromFile(getAssetPath() + "textures/rocks_normal_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.colorMap.loadFromFile(getAssetPath() + "textures/rocks_color_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - plane.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1: Fragment shader color map image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 2: Fragment combined normal and heightmap - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - // Binding 3: Fragment shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.vertexShader.descriptor), - // Binding 1: Fragment shader image sampler - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.colorMap.descriptor), - // Binding 2: Combined normal and heightmap - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.normalHeightMap.descriptor), - // Binding 3: Fragment shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3, &uniformBuffers.fragmentShader.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Tangent }); - - // Parallax mapping modes pipeline - shaderStages[0] = loadShader(getShadersPath() + "parallaxmapping/parallax.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "parallaxmapping/parallax.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareUniformBuffers() - { - // Vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.vertexShader, sizeof(UniformDataVertexShader))); - - // Fragment shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.fragmentShader, sizeof(UniformDataFragmentShader))); - // Map persistent - VK_CHECK_RESULT(uniformBuffers.vertexShader.map()); - VK_CHECK_RESULT(uniformBuffers.fragmentShader.map()); - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - // Vertex shader - uniformDataVertexShader.projection = camera.matrices.perspective; - uniformDataVertexShader.view = camera.matrices.view; - uniformDataVertexShader.model = glm::scale(glm::mat4(1.0f), glm::vec3(0.2f)); - - if (!paused) { - uniformDataVertexShader.lightPos.x = sin(glm::radians(timer * 360.0f)) * 1.5f; - uniformDataVertexShader.lightPos.z = cos(glm::radians(timer * 360.0f)) * 1.5f; - } - - uniformDataVertexShader.cameraPos = glm::vec4(camera.position, -1.0f) * -1.0f; - memcpy(uniformBuffers.vertexShader.mapped, &uniformDataVertexShader, sizeof(UniformDataVertexShader)); - - // Fragment shader - memcpy(uniformBuffers.fragmentShader.mapped, &uniformDataFragmentShader, sizeof(UniformDataFragmentShader)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - if (!paused || camera.updated) { - updateUniformBuffers(); - } - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->comboBox("Mode", &uniformDataFragmentShader.mappingMode, mappingModes)) { - updateUniformBuffers(); - } - } - } - -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/particlesystem/particlesystem.cpp b/examples/particlesystem/particlesystem.cpp deleted file mode 100644 index ca01acbf..00000000 --- a/examples/particlesystem/particlesystem.cpp +++ /dev/null @@ -1,565 +0,0 @@ -/* -* Vulkan Example - CPU based particle system -* -* This sample renders a particle system that is updated on the host (by the CPU) and rendered by the GPU using a vertex buffer -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -#define PARTICLE_COUNT 512 - -#define FLAME_RADIUS 8.0f - -// The particle system is made from two different particle types -// That type defines how a particle is rendered -#define PARTICLE_TYPE_FLAME 0 -#define PARTICLE_TYPE_SMOKE 1 - -struct Particle { - glm::vec4 pos; - glm::vec4 color; - float alpha; - float size; - float rotation; - uint32_t type; - glm::vec4 vel; - float rotationSpeed; -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - struct { - struct { - vks::Texture2D smoke; - vks::Texture2D fire; - // Use a custom sampler to change sampler attributes required for rotating the uvs in the shader for alpha blended textures - VkSampler sampler; - } particles; - struct { - vks::Texture2D colorMap; - vks::Texture2D normalMap; - } floor; - } textures{}; - - vkglTF::Model environment; - - // These parameters define the particle system behaviour - glm::vec3 emitterPos = glm::vec3(0.0f, -FLAME_RADIUS + 2.0f, 0.0f); - glm::vec3 minVel = glm::vec3(-3.0f, 0.5f, -3.0f); - glm::vec3 maxVel = glm::vec3(3.0f, 7.0f, 3.0f); - - struct Particles { - VkBuffer buffer{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - // Store the mapped address of the particle data for reuse - void *mappedMemory; - // Size of the particle buffer in bytes - size_t size{ 0 }; - } particles; - - struct { - vks::Buffer particles; - vks::Buffer environment; - } uniformBuffers; - - struct UniformDataParticles { - glm::mat4 projection; - glm::mat4 modelView; - // The viewport dimension is used by the particle system vertex shader - // to calculate the absolute point size based on the current viewport size - glm::vec2 viewportDim; - // This is the base point size for all particles - float pointSize{ 10.0f }; - } uniformDataParticles; - - struct UniformDataEnvironment { - glm::mat4 projection; - glm::mat4 modelView; - glm::mat4 normal; - glm::vec4 lightPos = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f); - } uniformDataEnvironment; - - struct { - VkPipeline particles{ VK_NULL_HANDLE }; - VkPipeline environment{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - struct { - VkDescriptorSet particles{ VK_NULL_HANDLE }; - VkDescriptorSet environment{ VK_NULL_HANDLE }; - } descriptorSets; - - std::vector particleBuffer{}; - - std::default_random_engine rndEngine; - - VulkanExample() : VulkanExampleBase() - { - title = "CPU based particle system"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -75.0f)); - camera.setRotation(glm::vec3(-15.0f, 45.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 1.0f, 256.0f); - timerSpeed *= 8.0f; - rndEngine.seed(benchmark.active ? 0 : (unsigned)time(nullptr)); - } - - ~VulkanExample() - { - if (device) { - textures.particles.smoke.destroy(); - textures.particles.fire.destroy(); - textures.floor.colorMap.destroy(); - textures.floor.normalMap.destroy(); - - vkDestroyPipeline(device, pipelines.particles, nullptr); - vkDestroyPipeline(device, pipelines.environment, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - vkUnmapMemory(device, particles.memory); - vkDestroyBuffer(device, particles.buffer, nullptr); - vkFreeMemory(device, particles.memory, nullptr); - - uniformBuffers.environment.destroy(); - uniformBuffers.particles.destroy(); - - vkDestroySampler(device, textures.particles.sampler, nullptr); - } - } - - virtual void getEnabledFeatures() - { - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - }; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0,0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - - // Environment - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.environment, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.environment); - environment.draw(drawCmdBuffers[i]); - - // Particle system (no index buffer) - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.particles, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.particles); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &particles.buffer, offsets); - vkCmdDraw(drawCmdBuffers[i], static_cast(particleBuffer.size()), 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - float rnd(float range) - { - std::uniform_real_distribution rndDist(0.0f, range); - return rndDist(rndEngine); - } - - void initParticle(Particle *particle, glm::vec3 emitterPos) - { - particle->vel = glm::vec4(0.0f, minVel.y + rnd(maxVel.y - minVel.y), 0.0f, 0.0f); - particle->alpha = rnd(0.75f); - particle->size = 1.0f + rnd(0.5f); - particle->color = glm::vec4(1.0f); - particle->type = PARTICLE_TYPE_FLAME; - particle->rotation = rnd(2.0f * float(M_PI)); - particle->rotationSpeed = rnd(2.0f) - rnd(2.0f); - - // Get random sphere point - float theta = rnd(2.0f * float(M_PI)); - float phi = rnd(float(M_PI)) - float(M_PI) / 2.0f; - float r = rnd(FLAME_RADIUS); - - particle->pos.x = r * cos(theta) * cos(phi); - particle->pos.y = r * sin(phi); - particle->pos.z = r * sin(theta) * cos(phi); - - particle->pos += glm::vec4(emitterPos, 0.0f); - } - - // Change the type of a particle, e.g. from flame to smoke - void transitionParticle(Particle *particle) - { - switch (particle->type) - { - case PARTICLE_TYPE_FLAME: - // Flame particles have a chance of turning into smoke - if (rnd(1.0f) < 0.05f) - { - particle->alpha = 0.0f; - particle->color = glm::vec4(0.25f + rnd(0.25f)); - particle->pos.x *= 0.5f; - particle->pos.z *= 0.5f; - particle->vel = glm::vec4(rnd(1.0f) - rnd(1.0f), (minVel.y * 2) + rnd(maxVel.y - minVel.y), rnd(1.0f) - rnd(1.0f), 0.0f); - particle->size = 1.0f + rnd(0.5f); - particle->rotationSpeed = rnd(1.0f) - rnd(1.0f); - particle->type = PARTICLE_TYPE_SMOKE; - } - else - { - initParticle(particle, emitterPos); - } - break; - case PARTICLE_TYPE_SMOKE: - // Respawn at end of life - initParticle(particle, emitterPos); - break; - } - } - - // Initialize the particle system and create a vertex buffer for rendering the particles - void prepareParticles() - { - particleBuffer.resize(PARTICLE_COUNT); - for (auto& particle : particleBuffer) - { - initParticle(&particle, emitterPos); - particle.alpha = 1.0f - (abs(particle.pos.y) / (FLAME_RADIUS * 2.0f)); - } - - particles.size = particleBuffer.size() * sizeof(Particle); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - particles.size, - &particles.buffer, - &particles.memory, - particleBuffer.data())); - - // Map the memory and store the pointer for reuse - VK_CHECK_RESULT(vkMapMemory(device, particles.memory, 0, particles.size, 0, &particles.mappedMemory)); - } - - // Update the state of all particles - void updateParticles() - { - float particleTimer = frameTimer * 0.45f; - for (auto& particle : particleBuffer) - { - switch (particle.type) - { - case PARTICLE_TYPE_FLAME: - particle.pos.y -= particle.vel.y * particleTimer * 3.5f; - particle.alpha += particleTimer * 2.5f; - particle.size -= particleTimer * 0.5f; - break; - case PARTICLE_TYPE_SMOKE: - particle.pos -= particle.vel * frameTimer * 1.0f; - particle.alpha += particleTimer * 1.25f; - particle.size += particleTimer * 0.125f; - particle.color -= particleTimer * 0.05f; - break; - } - particle.rotation += particleTimer * particle.rotationSpeed; - // If a particle has faded out, turn it into the other type (e.g. flame to smoke and vice versa) - if (particle.alpha > 2.0f) - { - transitionParticle(&particle); - } - } - - // Copy the updated particles to the vertex buffer - size_t size = particleBuffer.size() * sizeof(Particle); - memcpy(particles.mappedMemory, particleBuffer.data(), size); - } - - void loadAssets() - { - // Particles - textures.particles.smoke.loadFromFile(getAssetPath() + "textures/particle_smoke.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.particles.fire.loadFromFile(getAssetPath() + "textures/particle_fire.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - - // Floor - textures.floor.colorMap.loadFromFile(getAssetPath() + "textures/fireplace_colormap_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.floor.normalMap.loadFromFile(getAssetPath() + "textures/fireplace_normalmap_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - - // Create a custom sampler to be used with the particle textures - // Create sampler - VkSamplerCreateInfo samplerCreateInfo = vks::initializers::samplerCreateInfo(); - samplerCreateInfo.magFilter = VK_FILTER_LINEAR; - samplerCreateInfo.minFilter = VK_FILTER_LINEAR; - samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - // Different address mode - samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; - samplerCreateInfo.addressModeV = samplerCreateInfo.addressModeU; - samplerCreateInfo.addressModeW = samplerCreateInfo.addressModeU; - samplerCreateInfo.mipLodBias = 0.0f; - samplerCreateInfo.compareOp = VK_COMPARE_OP_NEVER; - samplerCreateInfo.minLod = 0.0f; - // Both particle textures have the same number of mip maps - samplerCreateInfo.maxLod = float(textures.particles.fire.mipLevels); - - if (vulkanDevice->features.samplerAnisotropy) - { - // Enable anisotropic filtering - samplerCreateInfo.maxAnisotropy = 8.0f; - samplerCreateInfo.anisotropyEnable = VK_TRUE; - } - - // Use a different border color (than the normal texture loader) for additive blending - samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerCreateInfo, nullptr, &textures.particles.sampler)); - - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - environment.loadFromFile(getAssetPath() + "models/fireplace.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT,2) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - std::vector writeDescriptorSets; - - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.particles)); - - // Image descriptor for the color map texture - VkDescriptorImageInfo texDescriptorSmoke = vks::initializers::descriptorImageInfo(textures.particles.sampler, textures.particles.smoke.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - VkDescriptorImageInfo texDescriptorFire = vks::initializers::descriptorImageInfo(textures.particles.sampler, textures.particles.fire.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.particles, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.particles.descriptor), - // Binding 1: Smoke texture - vks::initializers::writeDescriptorSet(descriptorSets.particles, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &texDescriptorSmoke), - // Binding 1: Fire texture array - vks::initializers::writeDescriptorSet(descriptorSets.particles, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &texDescriptorFire) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Environment - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.environment)); - writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.environment, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.environment.descriptor), - // Binding 1: Color map - vks::initializers::writeDescriptorSet(descriptorSets.environment, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.floor.colorMap.descriptor), - // Binding 2: Normal map - vks::initializers::writeDescriptorSet(descriptorSets.environment, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.floor.normalMap.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Particle rendering pipeline - { - // Vertex input state - VkVertexInputBindingDescription vertexInputBinding = - vks::initializers::vertexInputBindingDescription(0, sizeof(Particle), VK_VERTEX_INPUT_RATE_VERTEX); - - std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Particle, pos)), // Location 0: Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Particle, color)), // Location 1: Color - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32_SFLOAT, offsetof(Particle, alpha)), // Location 2: Alpha - vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32_SFLOAT, offsetof(Particle, size)), // Location 3: Size - vks::initializers::vertexInputAttributeDescription(0, 4, VK_FORMAT_R32_SFLOAT, offsetof(Particle, rotation)), // Location 4: Rotation - vks::initializers::vertexInputAttributeDescription(0, 5, VK_FORMAT_R32_SINT, offsetof(Particle, type)), // Location 5: Particle type - }; - - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = 1; - vertexInputState.pVertexBindingDescriptions = &vertexInputBinding; - vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - pipelineCI.pVertexInputState = &vertexInputState; - - // Don t' write to depth buffer - depthStencilState.depthWriteEnable = VK_FALSE; - - // Premulitplied alpha - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - - shaderStages[0] = loadShader(getShadersPath() + "particlesystem/particle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "particlesystem/particle.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.particles)); - } - - // Environment rendering pipeline (normal mapped) - { - // Vertex input state is taken from the glTF model loader - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Tangent }); - - blendAttachmentState.blendEnable = VK_FALSE; - depthStencilState.depthWriteEnable = VK_TRUE; - inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - - shaderStages[0] = loadShader(getShadersPath() + "particlesystem/normalmap.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "particlesystem/normalmap.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.environment)); - } - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.particles, sizeof(UniformDataParticles))); - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.environment, sizeof(UniformDataEnvironment))); - // Map persistent - VK_CHECK_RESULT(uniformBuffers.particles.map()); - VK_CHECK_RESULT(uniformBuffers.environment.map()); - } - - void updateUniformBuffers() - { - // Particle system fire - uniformDataParticles.projection = camera.matrices.perspective; - uniformDataParticles.modelView = camera.matrices.view; - uniformDataParticles.viewportDim = glm::vec2((float)width, (float)height); - memcpy(uniformBuffers.particles.mapped, &uniformDataParticles, sizeof(UniformDataParticles)); - - // Environment - uniformDataEnvironment.projection = camera.matrices.perspective; - uniformDataEnvironment.modelView = camera.matrices.view; - uniformDataEnvironment.normal = glm::inverseTranspose(uniformDataEnvironment.modelView); - // Update light position - if (!paused) { - uniformDataEnvironment.lightPos.x = sin(timer * 2.0f * float(M_PI)) * 1.5f; - uniformDataEnvironment.lightPos.y = 0.0f; - uniformDataEnvironment.lightPos.z = cos(timer * 2.0f * float(M_PI)) * 1.5f; - } - memcpy(uniformBuffers.environment.mapped, &uniformDataEnvironment, sizeof(UniformDataEnvironment)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareParticles(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - if (!paused) { - updateParticles(); - } - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/pbrbasic/pbrbasic.cpp b/examples/pbrbasic/pbrbasic.cpp deleted file mode 100644 index b62f84db..00000000 --- a/examples/pbrbasic/pbrbasic.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* -* Vulkan Example - Physical based shading basics -* -* See http://graphicrants.blogspot.de/2013/08/specular-brdf-reference.html for a good reference to the different functions that make up a specular BRDF -* -* Copyright (C) 2017-2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -struct Material { - // Parameter block used as push constant block - struct PushBlock { - float roughness; - float metallic; - float r, g, b; - } params{}; - std::string name; - Material() {}; - Material(std::string n, glm::vec3 c, float r, float m) : name(n) { - params.roughness = r; - params.metallic = m; - params.r = c.r; - params.g = c.g; - params.b = c.b; - }; -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - struct Meshes { - std::vector objects; - int32_t objectIndex = 0; - } models; - - struct { - vks::Buffer object; - vks::Buffer params; - } uniformBuffers; - - struct UBOMatrices { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - glm::vec3 camPos; - } uboMatrices; - - struct UBOParams { - glm::vec4 lights[4]; - } uboParams; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - // Default materials to select from - std::vector materials; - int32_t materialIndex = 0; - - std::vector materialNames; - std::vector objectNames; - - VulkanExample() : VulkanExampleBase() - { - title = "Physical based shading basics"; - camera.type = Camera::CameraType::firstperson; - camera.setPosition(glm::vec3(10.0f, 13.0f, 1.8f)); - camera.setRotation(glm::vec3(-62.5f, 90.0f, 0.0f)); - camera.movementSpeed = 4.0f; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - camera.rotationSpeed = 0.25f; - timerSpeed *= 0.25f; - - // Setup some default materials (source: https://seblagarde.wordpress.com/2011/08/17/feeding-a-physical-based-lighting-mode/) - materials.push_back(Material("Gold", glm::vec3(1.0f, 0.765557f, 0.336057f), 0.1f, 1.0f)); - materials.push_back(Material("Copper", glm::vec3(0.955008f, 0.637427f, 0.538163f), 0.1f, 1.0f)); - materials.push_back(Material("Chromium", glm::vec3(0.549585f, 0.556114f, 0.554256f), 0.1f, 1.0f)); - materials.push_back(Material("Nickel", glm::vec3(0.659777f, 0.608679f, 0.525649f), 0.1f, 1.0f)); - materials.push_back(Material("Titanium", glm::vec3(0.541931f, 0.496791f, 0.449419f), 0.1f, 1.0f)); - materials.push_back(Material("Cobalt", glm::vec3(0.662124f, 0.654864f, 0.633732f), 0.1f, 1.0f)); - materials.push_back(Material("Platinum", glm::vec3(0.672411f, 0.637331f, 0.585456f), 0.1f, 1.0f)); - // Testing materials - materials.push_back(Material("White", glm::vec3(1.0f), 0.1f, 1.0f)); - materials.push_back(Material("Red", glm::vec3(1.0f, 0.0f, 0.0f), 0.1f, 1.0f)); - materials.push_back(Material("Blue", glm::vec3(0.0f, 0.0f, 1.0f), 0.1f, 1.0f)); - materials.push_back(Material("Black", glm::vec3(0.0f), 0.1f, 1.0f)); - - for (auto material : materials) { - materialNames.push_back(material.name); - } - objectNames = { "Sphere", "Teapot", "Torusknot", "Venus" }; - - materialIndex = 0; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffers.object.destroy(); - uniformBuffers.params.destroy(); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Draw a grid of spheres using varying material parameters - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - Material mat = materials[materialIndex]; - - const uint32_t gridSize = 7; - - // Render a 2D grid of objects with varying PBR parameters - for (uint32_t y = 0; y < gridSize; y++) { - for (uint32_t x = 0; x < gridSize; x++) { - glm::vec3 pos = glm::vec3(float(x - (gridSize / 2.0f)) * 2.5f, 0.0f, float(y - (gridSize / 2.0f)) * 2.5f); - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::vec3), &pos); - // Vary metallic and roughness, two important PBR parameters - mat.params.metallic = glm::clamp((float)x / (float)(gridSize - 1), 0.1f, 1.0f); - mat.params.roughness = glm::clamp((float)y / (float)(gridSize - 1), 0.05f, 1.0f); - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(glm::vec3), sizeof(Material::PushBlock), &mat); - models.objects[models.objectIndex].draw(drawCmdBuffers[i]); - } - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - std::vector filenames = { "sphere.gltf", "teapot.gltf", "torusknot.gltf", "venus.gltf" }; - models.objects.resize(filenames.size()); - for (size_t i = 0; i < filenames.size(); i++) { - models.objects[i].loadFromFile(getAssetPath() + "models/" + filenames[i], vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.object.descriptor), - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, &uniformBuffers.params.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - } - - void preparePipelines() - { - // Layout - // We use push constant to pass material information - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - std::vector pushConstantRanges = { - vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::vec3), 0), - vks::initializers::pushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(Material::PushBlock), sizeof(glm::vec3)), - }; - pipelineLayoutCreateInfo.pushConstantRangeCount = 2; - pipelineLayoutCreateInfo.pPushConstantRanges = pushConstantRanges.data(); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - - std::array shaderStages; - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal }); - - // PBR pipeline - shaderStages[0] = loadShader(getShadersPath() + "pbrbasic/pbr.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbrbasic/pbr.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Enable depth test and write - depthStencilState.depthWriteEnable = VK_TRUE; - depthStencilState.depthTestEnable = VK_TRUE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Object vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.object, sizeof(uboMatrices))); - - // Shared parameter uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.params, sizeof(uboParams))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffers.object.map()); - VK_CHECK_RESULT(uniformBuffers.params.map()); - } - - void updateUniformBuffers() - { - // 3D object - uboMatrices.projection = camera.matrices.perspective; - uboMatrices.view = camera.matrices.view; - uboMatrices.model = glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f + (models.objectIndex == 1 ? 45.0f : 0.0f)), glm::vec3(0.0f, 1.0f, 0.0f)); - uboMatrices.camPos = camera.position * -1.0f; - memcpy(uniformBuffers.object.mapped, &uboMatrices, sizeof(uboMatrices)); - } - - void updateLights() - { - const float p = 15.0f; - uboParams.lights[0] = glm::vec4(-p, -p*0.5f, -p, 1.0f); - uboParams.lights[1] = glm::vec4(-p, -p*0.5f, p, 1.0f); - uboParams.lights[2] = glm::vec4( p, -p*0.5f, p, 1.0f); - uboParams.lights[3] = glm::vec4( p, -p*0.5f, -p, 1.0f); - - if (!paused) - { - uboParams.lights[0].x = sin(glm::radians(timer * 360.0f)) * 20.0f; - uboParams.lights[0].z = cos(glm::radians(timer * 360.0f)) * 20.0f; - uboParams.lights[1].x = cos(glm::radians(timer * 360.0f)) * 20.0f; - uboParams.lights[1].y = sin(glm::radians(timer * 360.0f)) * 20.0f; - } - - memcpy(uniformBuffers.params.mapped, &uboParams, sizeof(uboParams)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - if (!paused) { - updateLights(); - } - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->comboBox("Material", &materialIndex, materialNames)) { - buildCommandBuffers(); - } - if (overlay->comboBox("Object type", &models.objectIndex, objectNames)) { - updateUniformBuffers(); - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/pbribl/pbribl.cpp b/examples/pbribl/pbribl.cpp deleted file mode 100644 index 6c063b49..00000000 --- a/examples/pbribl/pbribl.cpp +++ /dev/null @@ -1,1420 +0,0 @@ -/* -* Vulkan Example - Physical based rendering with image based lighting -* -* This sample adds imaged based lighting from an environment map to the PBR equation -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -// For reference see http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -struct Material { - // Parameter block used as push constant block - struct PushBlock { - float roughness = 0.0f; - float metallic = 0.0f; - float specular = 0.0f; - float r, g, b; - } params; - std::string name; - Material() {}; - Material(std::string n, glm::vec3 c) : name(n) { - params.r = c.r; - params.g = c.g; - params.b = c.b; - }; -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - bool displaySkybox = true; - - struct Textures { - vks::TextureCubeMap environmentCube; - // Generated at runtime - vks::Texture2D lutBrdf; - vks::TextureCubeMap irradianceCube; - vks::TextureCubeMap prefilteredCube; - } textures; - - struct Meshes { - vkglTF::Model skybox; - std::vector objects; - int32_t objectIndex = 0; - } models; - - struct { - vks::Buffer object; - vks::Buffer skybox; - vks::Buffer params; - } uniformBuffers; - - struct UBOMatrices { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - glm::vec3 camPos; - } uboMatrices; - - struct UBOParams { - glm::vec4 lights[4]; - float exposure = 4.5f; - float gamma = 2.2f; - } uboParams; - - struct { - VkPipeline skybox{ VK_NULL_HANDLE }; - VkPipeline pbr{ VK_NULL_HANDLE }; - } pipelines; - - struct { - VkDescriptorSet object{ VK_NULL_HANDLE }; - VkDescriptorSet skybox{ VK_NULL_HANDLE }; - } descriptorSets; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - // Default materials to select from - std::vector materials; - int32_t materialIndex = 0; - - std::vector materialNames; - std::vector objectNames; - - VulkanExample() : VulkanExampleBase() - { - title = "PBR with image based lighting"; - - camera.type = Camera::CameraType::firstperson; - camera.movementSpeed = 4.0f; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - camera.rotationSpeed = 0.25f; - - camera.setRotation({ -3.75f, 180.0f, 0.0f }); - camera.setPosition({ 0.55f, 0.85f, 12.0f }); - - // Setup some default materials (source: https://seblagarde.wordpress.com/2011/08/17/feeding-a-physical-based-lighting-mode/) - materials.push_back(Material("Gold", glm::vec3(1.0f, 0.765557f, 0.336057f))); - materials.push_back(Material("Copper", glm::vec3(0.955008f, 0.637427f, 0.538163f))); - materials.push_back(Material("Chromium", glm::vec3(0.549585f, 0.556114f, 0.554256f))); - materials.push_back(Material("Nickel", glm::vec3(0.659777f, 0.608679f, 0.525649f))); - materials.push_back(Material("Titanium", glm::vec3(0.541931f, 0.496791f, 0.449419f))); - materials.push_back(Material("Cobalt", glm::vec3(0.662124f, 0.654864f, 0.633732f))); - materials.push_back(Material("Platinum", glm::vec3(0.672411f, 0.637331f, 0.585456f))); - // Testing materials - materials.push_back(Material("White", glm::vec3(1.0f))); - materials.push_back(Material("Dark", glm::vec3(0.1f))); - materials.push_back(Material("Black", glm::vec3(0.0f))); - materials.push_back(Material("Red", glm::vec3(1.0f, 0.0f, 0.0f))); - materials.push_back(Material("Blue", glm::vec3(0.0f, 0.0f, 1.0f))); - - for (auto material : materials) { - materialNames.push_back(material.name); - } - objectNames = { "Sphere", "Teapot", "Torusknot", "Venus" }; - - materialIndex = 9; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.skybox, nullptr); - vkDestroyPipeline(device, pipelines.pbr, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffers.object.destroy(); - uniformBuffers.skybox.destroy(); - uniformBuffers.params.destroy(); - textures.environmentCube.destroy(); - textures.irradianceCube.destroy(); - textures.prefilteredCube.destroy(); - textures.lutBrdf.destroy(); - } - } - - virtual void getEnabledFeatures() - { - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.1f, 0.1f, 0.1f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (size_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Skybox - if (displaySkybox) - { - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.skybox, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skybox); - models.skybox.draw(drawCmdBuffers[i]); - } - - // Objects - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.object, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.pbr); - - // Render a line of objects with the selected material and vary roughness/metallic material parameters - Material mat = materials[materialIndex]; - const uint32_t objcount = 10; - for (uint32_t x = 0; x < objcount; x++) { - glm::vec3 pos = glm::vec3(float(x - (objcount / 2.0f)) * 2.15f, 0.0f, 0.0f); - mat.params.roughness = 1.0f-glm::clamp((float)x / (float)objcount, 0.005f, 1.0f); - mat.params.metallic = glm::clamp((float)x / (float)objcount, 0.005f, 1.0f); - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::vec3), &pos); - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(glm::vec3), sizeof(Material::PushBlock), &mat); - models.objects[models.objectIndex].draw(drawCmdBuffers[i]); - - } - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY; - // Skybox - models.skybox.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - // Objects - std::vector filenames = { "sphere.gltf", "teapot.gltf", "torusknot.gltf", "venus.gltf" }; - models.objects.resize(filenames.size()); - for (size_t i = 0; i < filenames.size(); i++) { - models.objects[i].loadFromFile(getAssetPath() + "models/" + filenames[i], vulkanDevice, queue, glTFLoadingFlags); - } - // HDR cubemap - textures.environmentCube.loadFromFile(getAssetPath() + "textures/hdr/pisa_cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Descriptor Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor set layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 4), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Descriptor sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - // Objects - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.object)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.object.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, &uniformBuffers.params.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.irradianceCube.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &textures.lutBrdf.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4, &textures.prefilteredCube.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - - // Sky box - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.skybox)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.skybox.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, &uniformBuffers.params.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.environmentCube.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - } - - void preparePipelines() - { - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = - vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - - VkPipelineRasterizationStateCreateInfo rasterizationState = - vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); - - VkPipelineColorBlendAttachmentState blendAttachmentState = - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - - VkPipelineColorBlendStateCreateInfo colorBlendState = - vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - - VkPipelineDepthStencilStateCreateInfo depthStencilState = - vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - - VkPipelineViewportStateCreateInfo viewportState = - vks::initializers::pipelineViewportStateCreateInfo(1, 1); - - VkPipelineMultisampleStateCreateInfo multisampleState = - vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - - std::vector dynamicStateEnables = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR - }; - VkPipelineDynamicStateCreateInfo dynamicState = - vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - // Pipeline layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - // Push constant ranges - std::vector pushConstantRanges = { - vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::vec3), 0), - vks::initializers::pushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(Material::PushBlock), sizeof(glm::vec3)), - }; - pipelineLayoutCreateInfo.pushConstantRangeCount = 2; - pipelineLayoutCreateInfo.pPushConstantRanges = pushConstantRanges.data(); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - std::array shaderStages; - - // Pipelines - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - // Skybox pipeline (background cube) - shaderStages[0] = loadShader(getShadersPath() + "pbribl/skybox.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbribl/skybox.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.skybox)); - - // PBR pipeline - shaderStages[0] = loadShader(getShadersPath() + "pbribl/pbribl.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbribl/pbribl.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Enable depth test and write - depthStencilState.depthWriteEnable = VK_TRUE; - depthStencilState.depthTestEnable = VK_TRUE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.pbr)); - } - - // Generate a BRDF integration map used as a look-up-table (stores roughness / NdotV) - void generateBRDFLUT() - { - auto tStart = std::chrono::high_resolution_clock::now(); - - const VkFormat format = VK_FORMAT_R16G16_SFLOAT; // R16G16 is supported pretty much everywhere - const int32_t dim = 512; - - // Image - VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = format; - imageCI.extent.width = dim; - imageCI.extent.height = dim; - imageCI.extent.depth = 1; - imageCI.mipLevels = 1; - imageCI.arrayLayers = 1; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &textures.lutBrdf.image)); - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, textures.lutBrdf.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &textures.lutBrdf.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, textures.lutBrdf.image, textures.lutBrdf.deviceMemory, 0)); - // Image view - VkImageViewCreateInfo viewCI = vks::initializers::imageViewCreateInfo(); - viewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewCI.format = format; - viewCI.subresourceRange = {}; - viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewCI.subresourceRange.levelCount = 1; - viewCI.subresourceRange.layerCount = 1; - viewCI.image = textures.lutBrdf.image; - VK_CHECK_RESULT(vkCreateImageView(device, &viewCI, nullptr, &textures.lutBrdf.view)); - // Sampler - VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); - samplerCI.magFilter = VK_FILTER_LINEAR; - samplerCI.minFilter = VK_FILTER_LINEAR; - samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.minLod = 0.0f; - samplerCI.maxLod = 1.0f; - samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &textures.lutBrdf.sampler)); - - textures.lutBrdf.descriptor.imageView = textures.lutBrdf.view; - textures.lutBrdf.descriptor.sampler = textures.lutBrdf.sampler; - textures.lutBrdf.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - textures.lutBrdf.device = vulkanDevice; - - // FB, Att, RP, Pipe, etc. - VkAttachmentDescription attDesc = {}; - // Color attachment - attDesc.format = format; - attDesc.samples = VK_SAMPLE_COUNT_1_BIT; - attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attDesc.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Create the actual renderpass - VkRenderPassCreateInfo renderPassCI = vks::initializers::renderPassCreateInfo(); - renderPassCI.attachmentCount = 1; - renderPassCI.pAttachments = &attDesc; - renderPassCI.subpassCount = 1; - renderPassCI.pSubpasses = &subpassDescription; - renderPassCI.dependencyCount = 2; - renderPassCI.pDependencies = dependencies.data(); - - VkRenderPass renderpass; - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); - - VkFramebufferCreateInfo framebufferCI = vks::initializers::framebufferCreateInfo(); - framebufferCI.renderPass = renderpass; - framebufferCI.attachmentCount = 1; - framebufferCI.pAttachments = &textures.lutBrdf.view; - framebufferCI.width = dim; - framebufferCI.height = dim; - framebufferCI.layers = 1; - - VkFramebuffer framebuffer; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &framebufferCI, nullptr, &framebuffer)); - - // Descriptors - VkDescriptorSetLayout descriptorsetlayout; - std::vector setLayoutBindings = {}; - VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); - - // Descriptor Pool - std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; - VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VkDescriptorPool descriptorpool; - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); - - // Descriptor sets - VkDescriptorSet descriptorset; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); - - // Pipeline layout - VkPipelineLayout pipelinelayout; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = 2; - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = &emptyInputState; - - // Look-up-table (from BRDF) pipeline - shaderStages[0] = loadShader(getShadersPath() + "pbribl/genbrdflut.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbribl/genbrdflut.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VkPipeline pipeline; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - - // Render - VkClearValue clearValues[1]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderpass; - renderPassBeginInfo.renderArea.extent.width = dim; - renderPassBeginInfo.renderArea.extent.height = dim; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = clearValues; - renderPassBeginInfo.framebuffer = framebuffer; - - VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - vkCmdSetScissor(cmdBuf, 0, 1, &scissor); - vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdDraw(cmdBuf, 3, 1, 0, 0); - vkCmdEndRenderPass(cmdBuf); - vulkanDevice->flushCommandBuffer(cmdBuf, queue); - - vkQueueWaitIdle(queue); - - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelinelayout, nullptr); - vkDestroyRenderPass(device, renderpass, nullptr); - vkDestroyFramebuffer(device, framebuffer, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); - vkDestroyDescriptorPool(device, descriptorpool, nullptr); - - auto tEnd = std::chrono::high_resolution_clock::now(); - auto tDiff = std::chrono::duration(tEnd - tStart).count(); - std::cout << "Generating BRDF LUT took " << tDiff << " ms" << std::endl; - } - - // Generate an irradiance cube map from the environment cube map - void generateIrradianceCube() - { - auto tStart = std::chrono::high_resolution_clock::now(); - - const VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT; - const int32_t dim = 64; - const uint32_t numMips = static_cast(floor(log2(dim))) + 1; - - // Pre-filtered cube map - // Image - VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = format; - imageCI.extent.width = dim; - imageCI.extent.height = dim; - imageCI.extent.depth = 1; - imageCI.mipLevels = numMips; - imageCI.arrayLayers = 6; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - imageCI.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &textures.irradianceCube.image)); - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, textures.irradianceCube.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &textures.irradianceCube.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, textures.irradianceCube.image, textures.irradianceCube.deviceMemory, 0)); - // Image view - VkImageViewCreateInfo viewCI = vks::initializers::imageViewCreateInfo(); - viewCI.viewType = VK_IMAGE_VIEW_TYPE_CUBE; - viewCI.format = format; - viewCI.subresourceRange = {}; - viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewCI.subresourceRange.levelCount = numMips; - viewCI.subresourceRange.layerCount = 6; - viewCI.image = textures.irradianceCube.image; - VK_CHECK_RESULT(vkCreateImageView(device, &viewCI, nullptr, &textures.irradianceCube.view)); - // Sampler - VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); - samplerCI.magFilter = VK_FILTER_LINEAR; - samplerCI.minFilter = VK_FILTER_LINEAR; - samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.minLod = 0.0f; - samplerCI.maxLod = static_cast(numMips); - samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &textures.irradianceCube.sampler)); - - textures.irradianceCube.descriptor.imageView = textures.irradianceCube.view; - textures.irradianceCube.descriptor.sampler = textures.irradianceCube.sampler; - textures.irradianceCube.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - textures.irradianceCube.device = vulkanDevice; - - // FB, Att, RP, Pipe, etc. - VkAttachmentDescription attDesc = {}; - // Color attachment - attDesc.format = format; - attDesc.samples = VK_SAMPLE_COUNT_1_BIT; - attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Renderpass - VkRenderPassCreateInfo renderPassCI = vks::initializers::renderPassCreateInfo(); - renderPassCI.attachmentCount = 1; - renderPassCI.pAttachments = &attDesc; - renderPassCI.subpassCount = 1; - renderPassCI.pSubpasses = &subpassDescription; - renderPassCI.dependencyCount = 2; - renderPassCI.pDependencies = dependencies.data(); - VkRenderPass renderpass; - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); - - struct { - VkImage image; - VkImageView view; - VkDeviceMemory memory; - VkFramebuffer framebuffer; - } offscreen; - - // Offscreen framebuffer - { - // Color attachment - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.extent.width = dim; - imageCreateInfo.extent.height = dim; - imageCreateInfo.extent.depth = 1; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreen.image)); - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, offscreen.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreen.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreen.image, offscreen.memory, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = format; - colorImageView.flags = 0; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = offscreen.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreen.view)); - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = renderpass; - fbufCreateInfo.attachmentCount = 1; - fbufCreateInfo.pAttachments = &offscreen.view; - fbufCreateInfo.width = dim; - fbufCreateInfo.height = dim; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreen.framebuffer)); - - VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout( - layoutCmd, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); - } - - // Descriptors - VkDescriptorSetLayout descriptorsetlayout; - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); - - // Descriptor Pool - std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; - VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VkDescriptorPool descriptorpool; - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); - - // Descriptor sets - VkDescriptorSet descriptorset; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorset, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &textures.environmentCube.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - - // Pipeline layout - struct PushBlock { - glm::mat4 mvp; - // Sampling deltas - float deltaPhi = (2.0f * float(M_PI)) / 180.0f; - float deltaTheta = (0.5f * float(M_PI)) / 64.0f; - } pushBlock; - - VkPipelineLayout pipelinelayout; - std::vector pushConstantRanges = { - vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushBlock), 0), - }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = 2; - pipelineCI.pStages = shaderStages.data(); - pipelineCI.renderPass = renderpass; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - shaderStages[0] = loadShader(getShadersPath() + "pbribl/filtercube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbribl/irradiancecube.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VkPipeline pipeline; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - - // Render - - VkClearValue clearValues[1]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - // Reuse render pass from example pass - renderPassBeginInfo.renderPass = renderpass; - renderPassBeginInfo.framebuffer = offscreen.framebuffer; - renderPassBeginInfo.renderArea.extent.width = dim; - renderPassBeginInfo.renderArea.extent.height = dim; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = clearValues; - - std::vector matrices = { - // POSITIVE_X - glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_X - glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // POSITIVE_Y - glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_Y - glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // POSITIVE_Z - glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_Z - glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)), - }; - - VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); - - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - vkCmdSetScissor(cmdBuf, 0, 1, &scissor); - - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = numMips; - subresourceRange.layerCount = 6; - - // Change image layout for all cubemap faces to transfer destination - vks::tools::setImageLayout( - cmdBuf, - textures.irradianceCube.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - for (uint32_t m = 0; m < numMips; m++) { - for (uint32_t f = 0; f < 6; f++) { - viewport.width = static_cast(dim * std::pow(0.5f, m)); - viewport.height = static_cast(dim * std::pow(0.5f, m)); - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - - // Render scene from cube face's point of view - vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - // Update shader push constant block - pushBlock.mvp = glm::perspective((float)(M_PI / 2.0), 1.0f, 0.1f, 512.0f) * matrices[f]; - - vkCmdPushConstants(cmdBuf, pipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushBlock), &pushBlock); - - vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinelayout, 0, 1, &descriptorset, 0, NULL); - - models.skybox.draw(cmdBuf); - - vkCmdEndRenderPass(cmdBuf); - - vks::tools::setImageLayout( - cmdBuf, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - // Copy region for transfer from framebuffer to cube face - VkImageCopy copyRegion = {}; - - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset = { 0, 0, 0 }; - - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.baseArrayLayer = f; - copyRegion.dstSubresource.mipLevel = m; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset = { 0, 0, 0 }; - - copyRegion.extent.width = static_cast(viewport.width); - copyRegion.extent.height = static_cast(viewport.height); - copyRegion.extent.depth = 1; - - vkCmdCopyImage( - cmdBuf, - offscreen.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - textures.irradianceCube.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - ©Region); - - // Transform framebuffer color attachment back - vks::tools::setImageLayout( - cmdBuf, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } - } - - vks::tools::setImageLayout( - cmdBuf, - textures.irradianceCube.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - subresourceRange); - - vulkanDevice->flushCommandBuffer(cmdBuf, queue); - - vkDestroyRenderPass(device, renderpass, nullptr); - vkDestroyFramebuffer(device, offscreen.framebuffer, nullptr); - vkFreeMemory(device, offscreen.memory, nullptr); - vkDestroyImageView(device, offscreen.view, nullptr); - vkDestroyImage(device, offscreen.image, nullptr); - vkDestroyDescriptorPool(device, descriptorpool, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelinelayout, nullptr); - - auto tEnd = std::chrono::high_resolution_clock::now(); - auto tDiff = std::chrono::duration(tEnd - tStart).count(); - std::cout << "Generating irradiance cube with " << numMips << " mip levels took " << tDiff << " ms" << std::endl; - } - - // Prefilter environment cubemap - // See https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ - void generatePrefilteredCube() - { - auto tStart = std::chrono::high_resolution_clock::now(); - - const VkFormat format = VK_FORMAT_R16G16B16A16_SFLOAT; - const int32_t dim = 512; - const uint32_t numMips = static_cast(floor(log2(dim))) + 1; - - // Pre-filtered cube map - // Image - VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = format; - imageCI.extent.width = dim; - imageCI.extent.height = dim; - imageCI.extent.depth = 1; - imageCI.mipLevels = numMips; - imageCI.arrayLayers = 6; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - imageCI.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &textures.prefilteredCube.image)); - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, textures.prefilteredCube.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &textures.prefilteredCube.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, textures.prefilteredCube.image, textures.prefilteredCube.deviceMemory, 0)); - // Image view - VkImageViewCreateInfo viewCI = vks::initializers::imageViewCreateInfo(); - viewCI.viewType = VK_IMAGE_VIEW_TYPE_CUBE; - viewCI.format = format; - viewCI.subresourceRange = {}; - viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewCI.subresourceRange.levelCount = numMips; - viewCI.subresourceRange.layerCount = 6; - viewCI.image = textures.prefilteredCube.image; - VK_CHECK_RESULT(vkCreateImageView(device, &viewCI, nullptr, &textures.prefilteredCube.view)); - // Sampler - VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); - samplerCI.magFilter = VK_FILTER_LINEAR; - samplerCI.minFilter = VK_FILTER_LINEAR; - samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.minLod = 0.0f; - samplerCI.maxLod = static_cast(numMips); - samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &textures.prefilteredCube.sampler)); - - textures.prefilteredCube.descriptor.imageView = textures.prefilteredCube.view; - textures.prefilteredCube.descriptor.sampler = textures.prefilteredCube.sampler; - textures.prefilteredCube.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - textures.prefilteredCube.device = vulkanDevice; - - // FB, Att, RP, Pipe, etc. - VkAttachmentDescription attDesc = {}; - // Color attachment - attDesc.format = format; - attDesc.samples = VK_SAMPLE_COUNT_1_BIT; - attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Renderpass - VkRenderPassCreateInfo renderPassCI = vks::initializers::renderPassCreateInfo(); - renderPassCI.attachmentCount = 1; - renderPassCI.pAttachments = &attDesc; - renderPassCI.subpassCount = 1; - renderPassCI.pSubpasses = &subpassDescription; - renderPassCI.dependencyCount = 2; - renderPassCI.pDependencies = dependencies.data(); - VkRenderPass renderpass; - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); - - struct { - VkImage image; - VkImageView view; - VkDeviceMemory memory; - VkFramebuffer framebuffer; - } offscreen; - - // Offfscreen framebuffer - { - // Color attachment - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.extent.width = dim; - imageCreateInfo.extent.height = dim; - imageCreateInfo.extent.depth = 1; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreen.image)); - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, offscreen.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreen.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreen.image, offscreen.memory, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = format; - colorImageView.flags = 0; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = offscreen.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreen.view)); - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = renderpass; - fbufCreateInfo.attachmentCount = 1; - fbufCreateInfo.pAttachments = &offscreen.view; - fbufCreateInfo.width = dim; - fbufCreateInfo.height = dim; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreen.framebuffer)); - - VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout( - layoutCmd, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); - } - - // Descriptors - VkDescriptorSetLayout descriptorsetlayout; - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); - - // Descriptor Pool - std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; - VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VkDescriptorPool descriptorpool; - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); - - // Descriptor sets - VkDescriptorSet descriptorset; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorset, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &textures.environmentCube.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - - // Pipeline layout - struct PushBlock { - glm::mat4 mvp; - float roughness; - uint32_t numSamples = 32u; - } pushBlock; - - VkPipelineLayout pipelinelayout; - std::vector pushConstantRanges = { - vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushBlock), 0), - }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = 2; - pipelineCI.pStages = shaderStages.data(); - pipelineCI.renderPass = renderpass; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - shaderStages[0] = loadShader(getShadersPath() + "pbribl/filtercube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbribl/prefilterenvmap.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VkPipeline pipeline; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - - // Render - - VkClearValue clearValues[1]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - // Reuse render pass from example pass - renderPassBeginInfo.renderPass = renderpass; - renderPassBeginInfo.framebuffer = offscreen.framebuffer; - renderPassBeginInfo.renderArea.extent.width = dim; - renderPassBeginInfo.renderArea.extent.height = dim; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = clearValues; - - std::vector matrices = { - // POSITIVE_X - glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_X - glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // POSITIVE_Y - glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_Y - glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // POSITIVE_Z - glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_Z - glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)), - }; - - VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); - - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - vkCmdSetScissor(cmdBuf, 0, 1, &scissor); - - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = numMips; - subresourceRange.layerCount = 6; - - // Change image layout for all cubemap faces to transfer destination - vks::tools::setImageLayout( - cmdBuf, - textures.prefilteredCube.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - for (uint32_t m = 0; m < numMips; m++) { - pushBlock.roughness = (float)m / (float)(numMips - 1); - for (uint32_t f = 0; f < 6; f++) { - viewport.width = static_cast(dim * std::pow(0.5f, m)); - viewport.height = static_cast(dim * std::pow(0.5f, m)); - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - - // Render scene from cube face's point of view - vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - // Update shader push constant block - pushBlock.mvp = glm::perspective((float)(M_PI / 2.0), 1.0f, 0.1f, 512.0f) * matrices[f]; - - vkCmdPushConstants(cmdBuf, pipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushBlock), &pushBlock); - - vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinelayout, 0, 1, &descriptorset, 0, NULL); - - models.skybox.draw(cmdBuf); - - vkCmdEndRenderPass(cmdBuf); - - vks::tools::setImageLayout( - cmdBuf, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - // Copy region for transfer from framebuffer to cube face - VkImageCopy copyRegion = {}; - - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset = { 0, 0, 0 }; - - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.baseArrayLayer = f; - copyRegion.dstSubresource.mipLevel = m; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset = { 0, 0, 0 }; - - copyRegion.extent.width = static_cast(viewport.width); - copyRegion.extent.height = static_cast(viewport.height); - copyRegion.extent.depth = 1; - - vkCmdCopyImage( - cmdBuf, - offscreen.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - textures.prefilteredCube.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - ©Region); - - // Transform framebuffer color attachment back - vks::tools::setImageLayout( - cmdBuf, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } - } - - vks::tools::setImageLayout( - cmdBuf, - textures.prefilteredCube.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - subresourceRange); - - vulkanDevice->flushCommandBuffer(cmdBuf, queue); - - vkDestroyRenderPass(device, renderpass, nullptr); - vkDestroyFramebuffer(device, offscreen.framebuffer, nullptr); - vkFreeMemory(device, offscreen.memory, nullptr); - vkDestroyImageView(device, offscreen.view, nullptr); - vkDestroyImage(device, offscreen.image, nullptr); - vkDestroyDescriptorPool(device, descriptorpool, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelinelayout, nullptr); - - auto tEnd = std::chrono::high_resolution_clock::now(); - auto tDiff = std::chrono::duration(tEnd - tStart).count(); - std::cout << "Generating pre-filtered enivornment cube with " << numMips << " mip levels took " << tDiff << " ms" << std::endl; - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Object vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.object, - sizeof(uboMatrices))); - - // Skybox vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.skybox, - sizeof(uboMatrices))); - - // Shared parameter uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.params, - sizeof(uboParams))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffers.object.map()); - VK_CHECK_RESULT(uniformBuffers.skybox.map()); - VK_CHECK_RESULT(uniformBuffers.params.map()); - - updateUniformBuffers(); - updateParams(); - } - - void updateUniformBuffers() - { - // 3D object - uboMatrices.projection = camera.matrices.perspective; - uboMatrices.view = camera.matrices.view; - uboMatrices.model = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f + (models.objectIndex == 1 ? 45.0f : 0.0f)), glm::vec3(0.0f, 1.0f, 0.0f)); - uboMatrices.camPos = camera.position * -1.0f; - memcpy(uniformBuffers.object.mapped, &uboMatrices, sizeof(uboMatrices)); - - // Skybox - uboMatrices.model = glm::mat4(glm::mat3(camera.matrices.view)); - memcpy(uniformBuffers.skybox.mapped, &uboMatrices, sizeof(uboMatrices)); - } - - void updateParams() - { - const float p = 15.0f; - uboParams.lights[0] = glm::vec4(-p, -p*0.5f, -p, 1.0f); - uboParams.lights[1] = glm::vec4(-p, -p*0.5f, p, 1.0f); - uboParams.lights[2] = glm::vec4( p, -p*0.5f, p, 1.0f); - uboParams.lights[3] = glm::vec4( p, -p*0.5f, -p, 1.0f); - - memcpy(uniformBuffers.params.mapped, &uboParams, sizeof(uboParams)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - generateBRDFLUT(); - generateIrradianceCube(); - generatePrefilteredCube(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->comboBox("Material", &materialIndex, materialNames)) { - buildCommandBuffers(); - } - if (overlay->comboBox("Object type", &models.objectIndex, objectNames)) { - updateUniformBuffers(); - buildCommandBuffers(); - } - if (overlay->inputFloat("Exposure", &uboParams.exposure, 0.1f, 2)) { - updateParams(); - } - if (overlay->inputFloat("Gamma", &uboParams.gamma, 0.1f, 2)) { - updateParams(); - } - if (overlay->checkBox("Skybox", &displaySkybox)) { - buildCommandBuffers(); - } - } - } - -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/pbrtexture/pbrtexture.cpp b/examples/pbrtexture/pbrtexture.cpp deleted file mode 100644 index 74bf5733..00000000 --- a/examples/pbrtexture/pbrtexture.cpp +++ /dev/null @@ -1,1352 +0,0 @@ -/* -* Vulkan Example - Physical based rendering a textured object (metal/roughness workflow) with image based lighting -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -// For reference see http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool displaySkybox = true; - - struct Textures { - vks::TextureCubeMap environmentCube; - // Generated at runtime - vks::Texture2D lutBrdf; - vks::TextureCubeMap irradianceCube; - vks::TextureCubeMap prefilteredCube; - // Object texture maps - vks::Texture2D albedoMap; - vks::Texture2D normalMap; - vks::Texture2D aoMap; - vks::Texture2D metallicMap; - vks::Texture2D roughnessMap; - } textures; - - struct Meshes { - vkglTF::Model skybox; - vkglTF::Model object; - } models; - - struct { - vks::Buffer object; - vks::Buffer skybox; - vks::Buffer params; - } uniformBuffers; - - struct UBOMatrices { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - glm::vec3 camPos; - } uboMatrices; - - struct UBOParams { - glm::vec4 lights[4]; - float exposure = 4.5f; - float gamma = 2.2f; - } uboParams; - - struct { - VkPipeline skybox{ VK_NULL_HANDLE }; - VkPipeline pbr{ VK_NULL_HANDLE }; - } pipelines; - - struct { - VkDescriptorSet object{ VK_NULL_HANDLE }; - VkDescriptorSet skybox{ VK_NULL_HANDLE }; - } descriptorSets; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Textured PBR with IBL"; - - camera.type = Camera::CameraType::firstperson; - camera.movementSpeed = 4.0f; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - camera.rotationSpeed = 0.25f; - - camera.setRotation({ -7.75f, 150.25f, 0.0f }); - camera.setPosition({ 0.7f, 0.1f, 1.7f }); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.skybox, nullptr); - vkDestroyPipeline(device, pipelines.pbr, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - uniformBuffers.object.destroy(); - uniformBuffers.skybox.destroy(); - uniformBuffers.params.destroy(); - - textures.environmentCube.destroy(); - textures.irradianceCube.destroy(); - textures.prefilteredCube.destroy(); - textures.lutBrdf.destroy(); - textures.albedoMap.destroy(); - textures.normalMap.destroy(); - textures.aoMap.destroy(); - textures.metallicMap.destroy(); - textures.roughnessMap.destroy(); - } - } - - virtual void getEnabledFeatures() - { - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.1f, 0.1f, 0.1f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (size_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - - // Skybox - if (displaySkybox) - { - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.skybox, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skybox); - models.skybox.draw(drawCmdBuffers[i]); - } - - // Objects - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.object, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.pbr); - models.object.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.skybox.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.object.loadFromFile(getAssetPath() + "models/cerberus/cerberus.gltf", vulkanDevice, queue, glTFLoadingFlags); - textures.environmentCube.loadFromFile(getAssetPath() + "textures/hdr/gcanyon_cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue); - textures.albedoMap.loadFromFile(getAssetPath() + "models/cerberus/albedo.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.normalMap.loadFromFile(getAssetPath() + "models/cerberus/normal.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.aoMap.loadFromFile(getAssetPath() + "models/cerberus/ao.ktx", VK_FORMAT_R8_UNORM, vulkanDevice, queue); - textures.metallicMap.loadFromFile(getAssetPath() + "models/cerberus/metallic.ktx", VK_FORMAT_R8_UNORM, vulkanDevice, queue); - textures.roughnessMap.loadFromFile(getAssetPath() + "models/cerberus/roughness.ktx", VK_FORMAT_R8_UNORM, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Descriptor Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 16) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor set layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 4), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 5), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 6), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 7), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 8), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 9), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Descriptor sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - // Objects - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.object)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.object.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, &uniformBuffers.params.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.irradianceCube.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &textures.lutBrdf.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4, &textures.prefilteredCube.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 5, &textures.albedoMap.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6, &textures.normalMap.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 7, &textures.aoMap.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 8, &textures.metallicMap.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 9, &textures.roughnessMap.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - - // Sky box - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.skybox)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.skybox.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, &uniformBuffers.params.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.environmentCube.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - } - - void preparePipelines() - { - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Pipeline layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Tangent }); - - // Skybox pipeline (background cube) - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - shaderStages[0] = loadShader(getShadersPath() + "pbrtexture/skybox.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbrtexture/skybox.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.skybox)); - - // PBR pipeline - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - shaderStages[0] = loadShader(getShadersPath() + "pbrtexture/pbrtexture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbrtexture/pbrtexture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Enable depth test and write - depthStencilState.depthWriteEnable = VK_TRUE; - depthStencilState.depthTestEnable = VK_TRUE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.pbr)); - } - - // Generate a BRDF integration map used as a look-up-table (stores roughness / NdotV) - void generateBRDFLUT() - { - auto tStart = std::chrono::high_resolution_clock::now(); - - const VkFormat format = VK_FORMAT_R16G16_SFLOAT; // R16G16 is supported pretty much everywhere - const int32_t dim = 512; - - // Image - VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = format; - imageCI.extent.width = dim; - imageCI.extent.height = dim; - imageCI.extent.depth = 1; - imageCI.mipLevels = 1; - imageCI.arrayLayers = 1; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &textures.lutBrdf.image)); - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, textures.lutBrdf.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &textures.lutBrdf.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, textures.lutBrdf.image, textures.lutBrdf.deviceMemory, 0)); - // Image view - VkImageViewCreateInfo viewCI = vks::initializers::imageViewCreateInfo(); - viewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewCI.format = format; - viewCI.subresourceRange = {}; - viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewCI.subresourceRange.levelCount = 1; - viewCI.subresourceRange.layerCount = 1; - viewCI.image = textures.lutBrdf.image; - VK_CHECK_RESULT(vkCreateImageView(device, &viewCI, nullptr, &textures.lutBrdf.view)); - // Sampler - VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); - samplerCI.magFilter = VK_FILTER_LINEAR; - samplerCI.minFilter = VK_FILTER_LINEAR; - samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.minLod = 0.0f; - samplerCI.maxLod = 1.0f; - samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &textures.lutBrdf.sampler)); - - textures.lutBrdf.descriptor.imageView = textures.lutBrdf.view; - textures.lutBrdf.descriptor.sampler = textures.lutBrdf.sampler; - textures.lutBrdf.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - textures.lutBrdf.device = vulkanDevice; - - // FB, Att, RP, Pipe, etc. - VkAttachmentDescription attDesc = {}; - // Color attachment - attDesc.format = format; - attDesc.samples = VK_SAMPLE_COUNT_1_BIT; - attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attDesc.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Create the actual renderpass - VkRenderPassCreateInfo renderPassCI = vks::initializers::renderPassCreateInfo(); - renderPassCI.attachmentCount = 1; - renderPassCI.pAttachments = &attDesc; - renderPassCI.subpassCount = 1; - renderPassCI.pSubpasses = &subpassDescription; - renderPassCI.dependencyCount = 2; - renderPassCI.pDependencies = dependencies.data(); - - VkRenderPass renderpass; - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); - - VkFramebufferCreateInfo framebufferCI = vks::initializers::framebufferCreateInfo(); - framebufferCI.renderPass = renderpass; - framebufferCI.attachmentCount = 1; - framebufferCI.pAttachments = &textures.lutBrdf.view; - framebufferCI.width = dim; - framebufferCI.height = dim; - framebufferCI.layers = 1; - - VkFramebuffer framebuffer; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &framebufferCI, nullptr, &framebuffer)); - - // Descriptors - VkDescriptorSetLayout descriptorsetlayout; - std::vector setLayoutBindings = {}; - VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); - - // Descriptor Pool - std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; - VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VkDescriptorPool descriptorpool; - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); - - // Descriptor sets - VkDescriptorSet descriptorset; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); - - // Pipeline layout - VkPipelineLayout pipelinelayout; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = 2; - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = &emptyInputState; - - // Look-up-table (from BRDF) pipeline - shaderStages[0] = loadShader(getShadersPath() + "pbrtexture/genbrdflut.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbrtexture/genbrdflut.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VkPipeline pipeline; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - - // Render - VkClearValue clearValues[1]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderpass; - renderPassBeginInfo.renderArea.extent.width = dim; - renderPassBeginInfo.renderArea.extent.height = dim; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = clearValues; - renderPassBeginInfo.framebuffer = framebuffer; - - VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - vkCmdSetScissor(cmdBuf, 0, 1, &scissor); - vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdDraw(cmdBuf, 3, 1, 0, 0); - vkCmdEndRenderPass(cmdBuf); - vulkanDevice->flushCommandBuffer(cmdBuf, queue); - - vkQueueWaitIdle(queue); - - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelinelayout, nullptr); - vkDestroyRenderPass(device, renderpass, nullptr); - vkDestroyFramebuffer(device, framebuffer, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); - vkDestroyDescriptorPool(device, descriptorpool, nullptr); - - auto tEnd = std::chrono::high_resolution_clock::now(); - auto tDiff = std::chrono::duration(tEnd - tStart).count(); - std::cout << "Generating BRDF LUT took " << tDiff << " ms" << std::endl; - } - - // Generate an irradiance cube map from the environment cube map - void generateIrradianceCube() - { - auto tStart = std::chrono::high_resolution_clock::now(); - - const VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT; - const int32_t dim = 64; - const uint32_t numMips = static_cast(floor(log2(dim))) + 1; - - // Pre-filtered cube map - // Image - VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = format; - imageCI.extent.width = dim; - imageCI.extent.height = dim; - imageCI.extent.depth = 1; - imageCI.mipLevels = numMips; - imageCI.arrayLayers = 6; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - imageCI.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &textures.irradianceCube.image)); - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, textures.irradianceCube.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &textures.irradianceCube.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, textures.irradianceCube.image, textures.irradianceCube.deviceMemory, 0)); - // Image view - VkImageViewCreateInfo viewCI = vks::initializers::imageViewCreateInfo(); - viewCI.viewType = VK_IMAGE_VIEW_TYPE_CUBE; - viewCI.format = format; - viewCI.subresourceRange = {}; - viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewCI.subresourceRange.levelCount = numMips; - viewCI.subresourceRange.layerCount = 6; - viewCI.image = textures.irradianceCube.image; - VK_CHECK_RESULT(vkCreateImageView(device, &viewCI, nullptr, &textures.irradianceCube.view)); - // Sampler - VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); - samplerCI.magFilter = VK_FILTER_LINEAR; - samplerCI.minFilter = VK_FILTER_LINEAR; - samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.minLod = 0.0f; - samplerCI.maxLod = static_cast(numMips); - samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &textures.irradianceCube.sampler)); - - textures.irradianceCube.descriptor.imageView = textures.irradianceCube.view; - textures.irradianceCube.descriptor.sampler = textures.irradianceCube.sampler; - textures.irradianceCube.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - textures.irradianceCube.device = vulkanDevice; - - // FB, Att, RP, Pipe, etc. - VkAttachmentDescription attDesc = {}; - // Color attachment - attDesc.format = format; - attDesc.samples = VK_SAMPLE_COUNT_1_BIT; - attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Renderpass - VkRenderPassCreateInfo renderPassCI = vks::initializers::renderPassCreateInfo(); - renderPassCI.attachmentCount = 1; - renderPassCI.pAttachments = &attDesc; - renderPassCI.subpassCount = 1; - renderPassCI.pSubpasses = &subpassDescription; - renderPassCI.dependencyCount = 2; - renderPassCI.pDependencies = dependencies.data(); - VkRenderPass renderpass; - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); - - struct { - VkImage image; - VkImageView view; - VkDeviceMemory memory; - VkFramebuffer framebuffer; - } offscreen; - - // Offfscreen framebuffer - { - // Color attachment - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.extent.width = dim; - imageCreateInfo.extent.height = dim; - imageCreateInfo.extent.depth = 1; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreen.image)); - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, offscreen.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreen.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreen.image, offscreen.memory, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = format; - colorImageView.flags = 0; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = offscreen.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreen.view)); - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = renderpass; - fbufCreateInfo.attachmentCount = 1; - fbufCreateInfo.pAttachments = &offscreen.view; - fbufCreateInfo.width = dim; - fbufCreateInfo.height = dim; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreen.framebuffer)); - - VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout( - layoutCmd, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); - } - - // Descriptors - VkDescriptorSetLayout descriptorsetlayout; - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); - - // Descriptor Pool - std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; - VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VkDescriptorPool descriptorpool; - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); - - // Descriptor sets - VkDescriptorSet descriptorset; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorset, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &textures.environmentCube.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - - // Pipeline layout - struct PushBlock { - glm::mat4 mvp; - // Sampling deltas - float deltaPhi = (2.0f * float(M_PI)) / 180.0f; - float deltaTheta = (0.5f * float(M_PI)) / 64.0f; - } pushBlock; - - VkPipelineLayout pipelinelayout; - std::vector pushConstantRanges = { - vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushBlock), 0), - }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = 2; - pipelineCI.pStages = shaderStages.data(); - pipelineCI.renderPass = renderpass; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - shaderStages[0] = loadShader(getShadersPath() + "pbrtexture/filtercube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbrtexture/irradiancecube.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VkPipeline pipeline; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - - // Render - - VkClearValue clearValues[1]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - // Reuse render pass from example pass - renderPassBeginInfo.renderPass = renderpass; - renderPassBeginInfo.framebuffer = offscreen.framebuffer; - renderPassBeginInfo.renderArea.extent.width = dim; - renderPassBeginInfo.renderArea.extent.height = dim; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = clearValues; - - std::vector matrices = { - // POSITIVE_X - glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_X - glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // POSITIVE_Y - glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_Y - glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // POSITIVE_Z - glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_Z - glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)), - }; - - VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); - - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - vkCmdSetScissor(cmdBuf, 0, 1, &scissor); - - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = numMips; - subresourceRange.layerCount = 6; - - // Change image layout for all cubemap faces to transfer destination - vks::tools::setImageLayout( - cmdBuf, - textures.irradianceCube.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - for (uint32_t m = 0; m < numMips; m++) { - for (uint32_t f = 0; f < 6; f++) { - viewport.width = static_cast(dim * std::pow(0.5f, m)); - viewport.height = static_cast(dim * std::pow(0.5f, m)); - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - - // Render scene from cube face's point of view - vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - // Update shader push constant block - pushBlock.mvp = glm::perspective((float)(M_PI / 2.0), 1.0f, 0.1f, 512.0f) * matrices[f]; - - vkCmdPushConstants(cmdBuf, pipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushBlock), &pushBlock); - - vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinelayout, 0, 1, &descriptorset, 0, NULL); - - models.skybox.draw(cmdBuf); - - vkCmdEndRenderPass(cmdBuf); - - vks::tools::setImageLayout( - cmdBuf, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - // Copy region for transfer from framebuffer to cube face - VkImageCopy copyRegion = {}; - - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset = { 0, 0, 0 }; - - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.baseArrayLayer = f; - copyRegion.dstSubresource.mipLevel = m; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset = { 0, 0, 0 }; - - copyRegion.extent.width = static_cast(viewport.width); - copyRegion.extent.height = static_cast(viewport.height); - copyRegion.extent.depth = 1; - - vkCmdCopyImage( - cmdBuf, - offscreen.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - textures.irradianceCube.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - ©Region); - - // Transform framebuffer color attachment back - vks::tools::setImageLayout( - cmdBuf, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } - } - - vks::tools::setImageLayout( - cmdBuf, - textures.irradianceCube.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - subresourceRange); - - vulkanDevice->flushCommandBuffer(cmdBuf, queue); - - vkDestroyRenderPass(device, renderpass, nullptr); - vkDestroyFramebuffer(device, offscreen.framebuffer, nullptr); - vkFreeMemory(device, offscreen.memory, nullptr); - vkDestroyImageView(device, offscreen.view, nullptr); - vkDestroyImage(device, offscreen.image, nullptr); - vkDestroyDescriptorPool(device, descriptorpool, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelinelayout, nullptr); - - auto tEnd = std::chrono::high_resolution_clock::now(); - auto tDiff = std::chrono::duration(tEnd - tStart).count(); - std::cout << "Generating irradiance cube with " << numMips << " mip levels took " << tDiff << " ms" << std::endl; - } - - // Prefilter environment cubemap - // See https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ - void generatePrefilteredCube() - { - auto tStart = std::chrono::high_resolution_clock::now(); - - const VkFormat format = VK_FORMAT_R16G16B16A16_SFLOAT; - const int32_t dim = 512; - const uint32_t numMips = static_cast(floor(log2(dim))) + 1; - - // Pre-filtered cube map - // Image - VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = format; - imageCI.extent.width = dim; - imageCI.extent.height = dim; - imageCI.extent.depth = 1; - imageCI.mipLevels = numMips; - imageCI.arrayLayers = 6; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - imageCI.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &textures.prefilteredCube.image)); - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, textures.prefilteredCube.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &textures.prefilteredCube.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, textures.prefilteredCube.image, textures.prefilteredCube.deviceMemory, 0)); - // Image view - VkImageViewCreateInfo viewCI = vks::initializers::imageViewCreateInfo(); - viewCI.viewType = VK_IMAGE_VIEW_TYPE_CUBE; - viewCI.format = format; - viewCI.subresourceRange = {}; - viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewCI.subresourceRange.levelCount = numMips; - viewCI.subresourceRange.layerCount = 6; - viewCI.image = textures.prefilteredCube.image; - VK_CHECK_RESULT(vkCreateImageView(device, &viewCI, nullptr, &textures.prefilteredCube.view)); - // Sampler - VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); - samplerCI.magFilter = VK_FILTER_LINEAR; - samplerCI.minFilter = VK_FILTER_LINEAR; - samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.minLod = 0.0f; - samplerCI.maxLod = static_cast(numMips); - samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &textures.prefilteredCube.sampler)); - - textures.prefilteredCube.descriptor.imageView = textures.prefilteredCube.view; - textures.prefilteredCube.descriptor.sampler = textures.prefilteredCube.sampler; - textures.prefilteredCube.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - textures.prefilteredCube.device = vulkanDevice; - - // FB, Att, RP, Pipe, etc. - VkAttachmentDescription attDesc = {}; - // Color attachment - attDesc.format = format; - attDesc.samples = VK_SAMPLE_COUNT_1_BIT; - attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Renderpass - VkRenderPassCreateInfo renderPassCI = vks::initializers::renderPassCreateInfo(); - renderPassCI.attachmentCount = 1; - renderPassCI.pAttachments = &attDesc; - renderPassCI.subpassCount = 1; - renderPassCI.pSubpasses = &subpassDescription; - renderPassCI.dependencyCount = 2; - renderPassCI.pDependencies = dependencies.data(); - VkRenderPass renderpass; - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); - - struct { - VkImage image; - VkImageView view; - VkDeviceMemory memory; - VkFramebuffer framebuffer; - } offscreen; - - // Offfscreen framebuffer - { - // Color attachment - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.extent.width = dim; - imageCreateInfo.extent.height = dim; - imageCreateInfo.extent.depth = 1; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreen.image)); - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, offscreen.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreen.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreen.image, offscreen.memory, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = format; - colorImageView.flags = 0; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = offscreen.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreen.view)); - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = renderpass; - fbufCreateInfo.attachmentCount = 1; - fbufCreateInfo.pAttachments = &offscreen.view; - fbufCreateInfo.width = dim; - fbufCreateInfo.height = dim; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreen.framebuffer)); - - VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout( - layoutCmd, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); - } - - // Descriptors - VkDescriptorSetLayout descriptorsetlayout; - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); - - // Descriptor Pool - std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; - VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VkDescriptorPool descriptorpool; - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); - - // Descriptor sets - VkDescriptorSet descriptorset; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorset, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &textures.environmentCube.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - - // Pipeline layout - struct PushBlock { - glm::mat4 mvp; - float roughness; - uint32_t numSamples = 32u; - } pushBlock; - - VkPipelineLayout pipelinelayout; - std::vector pushConstantRanges = { - vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushBlock), 0), - }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = 2; - pipelineCI.pStages = shaderStages.data(); - pipelineCI.renderPass = renderpass; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - shaderStages[0] = loadShader(getShadersPath() + "pbrtexture/filtercube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pbrtexture/prefilterenvmap.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VkPipeline pipeline; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - - // Render - - VkClearValue clearValues[1]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - // Reuse render pass from example pass - renderPassBeginInfo.renderPass = renderpass; - renderPassBeginInfo.framebuffer = offscreen.framebuffer; - renderPassBeginInfo.renderArea.extent.width = dim; - renderPassBeginInfo.renderArea.extent.height = dim; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = clearValues; - - std::vector matrices = { - // POSITIVE_X - glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_X - glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // POSITIVE_Y - glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_Y - glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // POSITIVE_Z - glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_Z - glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)), - }; - - VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); - - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - vkCmdSetScissor(cmdBuf, 0, 1, &scissor); - - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = numMips; - subresourceRange.layerCount = 6; - - // Change image layout for all cubemap faces to transfer destination - vks::tools::setImageLayout( - cmdBuf, - textures.prefilteredCube.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - for (uint32_t m = 0; m < numMips; m++) { - pushBlock.roughness = (float)m / (float)(numMips - 1); - for (uint32_t f = 0; f < 6; f++) { - viewport.width = static_cast(dim * std::pow(0.5f, m)); - viewport.height = static_cast(dim * std::pow(0.5f, m)); - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - - // Render scene from cube face's point of view - vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - // Update shader push constant block - pushBlock.mvp = glm::perspective((float)(M_PI / 2.0), 1.0f, 0.1f, 512.0f) * matrices[f]; - - vkCmdPushConstants(cmdBuf, pipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushBlock), &pushBlock); - - vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinelayout, 0, 1, &descriptorset, 0, NULL); - - models.skybox.draw(cmdBuf); - - vkCmdEndRenderPass(cmdBuf); - - vks::tools::setImageLayout( - cmdBuf, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - // Copy region for transfer from framebuffer to cube face - VkImageCopy copyRegion = {}; - - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset = { 0, 0, 0 }; - - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.baseArrayLayer = f; - copyRegion.dstSubresource.mipLevel = m; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset = { 0, 0, 0 }; - - copyRegion.extent.width = static_cast(viewport.width); - copyRegion.extent.height = static_cast(viewport.height); - copyRegion.extent.depth = 1; - - vkCmdCopyImage( - cmdBuf, - offscreen.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - textures.prefilteredCube.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - ©Region); - - // Transform framebuffer color attachment back - vks::tools::setImageLayout( - cmdBuf, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } - } - - vks::tools::setImageLayout( - cmdBuf, - textures.prefilteredCube.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - subresourceRange); - - vulkanDevice->flushCommandBuffer(cmdBuf, queue); - - vkDestroyRenderPass(device, renderpass, nullptr); - vkDestroyFramebuffer(device, offscreen.framebuffer, nullptr); - vkFreeMemory(device, offscreen.memory, nullptr); - vkDestroyImageView(device, offscreen.view, nullptr); - vkDestroyImage(device, offscreen.image, nullptr); - vkDestroyDescriptorPool(device, descriptorpool, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelinelayout, nullptr); - - auto tEnd = std::chrono::high_resolution_clock::now(); - auto tDiff = std::chrono::duration(tEnd - tStart).count(); - std::cout << "Generating pre-filtered enivornment cube with " << numMips << " mip levels took " << tDiff << " ms" << std::endl; - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Object vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.object, - sizeof(uboMatrices))); - - // Skybox vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.skybox, - sizeof(uboMatrices))); - - // Shared parameter uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.params, - sizeof(uboParams))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffers.object.map()); - VK_CHECK_RESULT(uniformBuffers.skybox.map()); - VK_CHECK_RESULT(uniformBuffers.params.map()); - - updateUniformBuffers(); - updateParams(); - } - - void updateUniformBuffers() - { - // 3D object - uboMatrices.projection = camera.matrices.perspective; - uboMatrices.view = camera.matrices.view; - uboMatrices.model = glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)); - uboMatrices.camPos = camera.position * -1.0f; - memcpy(uniformBuffers.object.mapped, &uboMatrices, sizeof(uboMatrices)); - - // Skybox - uboMatrices.model = glm::mat4(glm::mat3(camera.matrices.view)); - memcpy(uniformBuffers.skybox.mapped, &uboMatrices, sizeof(uboMatrices)); - } - - void updateParams() - { - const float p = 15.0f; - uboParams.lights[0] = glm::vec4(-p, -p*0.5f, -p, 1.0f); - uboParams.lights[1] = glm::vec4(-p, -p*0.5f, p, 1.0f); - uboParams.lights[2] = glm::vec4( p, -p*0.5f, p, 1.0f); - uboParams.lights[3] = glm::vec4( p, -p*0.5f, -p, 1.0f); - - memcpy(uniformBuffers.params.mapped, &uboParams, sizeof(uboParams)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - generateBRDFLUT(); - generateIrradianceCube(); - generatePrefilteredCube(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->inputFloat("Exposure", &uboParams.exposure, 0.1f, 2)) { - updateParams(); - } - if (overlay->inputFloat("Gamma", &uboParams.gamma, 0.1f, 2)) { - updateParams(); - } - if (overlay->checkBox("Skybox", &displaySkybox)) { - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/pipelines/pipelines.cpp b/examples/pipelines/pipelines.cpp deleted file mode 100644 index 7f812536..00000000 --- a/examples/pipelines/pipelines.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* -* Vulkan Example - Using different pipelines in a single renderpass -* -* This sample shows how to setup multiple graphics pipelines and how to use them for drawing objects with differring visuals -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample: public VulkanExampleBase -{ -public: - vkglTF::Model scene; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 lightPos{ 0.0f, 2.0f, 1.0f, 0.0f }; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - struct { - VkPipeline phong{ VK_NULL_HANDLE }; - VkPipeline wireframe{ VK_NULL_HANDLE }; - VkPipeline toon{ VK_NULL_HANDLE }; - } pipelines; - - VulkanExample() : VulkanExampleBase() - { - title = "Pipeline state objects"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -10.5f)); - camera.setRotation(glm::vec3(-25.0f, 15.0f, 0.0f)); - camera.setRotationSpeed(0.5f); - camera.setPerspective(60.0f, (float)(width / 3.0f) / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.phong, nullptr); - if (enabledFeatures.fillModeNonSolid) - { - vkDestroyPipeline(device, pipelines.wireframe, nullptr); - } - vkDestroyPipeline(device, pipelines.toon, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - uniformBuffer.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Fill mode non solid is required for wireframe display - if (deviceFeatures.fillModeNonSolid) { - enabledFeatures.fillModeNonSolid = VK_TRUE; - }; - - // Wide lines must be present for line width > 1.0f - if (deviceFeatures.wideLines) { - enabledFeatures.wideLines = VK_TRUE; - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - scene.bindBuffers(drawCmdBuffers[i]); - - // Left : Render the scene using the solid colored pipeline with phong shading - viewport.width = (float)width / 3.0f; - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phong); - vkCmdSetLineWidth(drawCmdBuffers[i], 1.0f); - scene.draw(drawCmdBuffers[i]); - - // Center : Render the scene using a toon style pipeline - viewport.x = (float)width / 3.0f; - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.toon); - // Line width > 1.0f only if wide lines feature is supported - if (enabledFeatures.wideLines) { - vkCmdSetLineWidth(drawCmdBuffers[i], 2.0f); - } - scene.draw(drawCmdBuffers[i]); - - // Right : Render the scene as wireframe (if that feature is supported by the implementation) - if (enabledFeatures.fillModeNonSolid) { - viewport.x = (float)width / 3.0f + (float)width / 3.0f; - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.wireframe); - scene.draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - scene.loadFromFile(getAssetPath() + "models/treasure_smooth.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - - // Most state is shared between all pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH, }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); - - // Create the different pipelines used in this sample - - // We are using this pipeline as the base for the other pipelines (derivatives) - // Pipeline derivatives can be used for pipelines that share most of their state - // Depending on the implementation this may result in better performance for pipeline - // switching and faster creation time - pipelineCI.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT; - - // Textured pipeline - // Phong shading pipeline - shaderStages[0] = loadShader(getShadersPath() + "pipelines/phong.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pipelines/phong.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.phong)); - - // All pipelines created after the base pipeline will be derivatives - pipelineCI.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; - // Base pipeline will be our first created pipeline - pipelineCI.basePipelineHandle = pipelines.phong; - // It's only allowed to either use a handle or index for the base pipeline - // As we use the handle, we must set the index to -1 (see section 9.5 of the specification) - pipelineCI.basePipelineIndex = -1; - - // Toon shading pipeline - shaderStages[0] = loadShader(getShadersPath() + "pipelines/toon.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pipelines/toon.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.toon)); - - // Pipeline for wire frame rendering - // Non solid rendering is not a mandatory Vulkan feature - if (enabledFeatures.fillModeNonSolid) { - rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; - shaderStages[0] = loadShader(getShadersPath() + "pipelines/wireframe.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pipelines/wireframe.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); - } - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Create the vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - // Override the base sample camera setup, since we use three viewports - camera.setPerspective(60.0f, (float)(width / 3.0f) / (float)height, 0.1f, 256.0f); - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (!enabledFeatures.fillModeNonSolid) { - if (overlay->header("Info")) { - overlay->text("Non solid fill modes not supported!"); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/pipelinestatistics/pipelinestatistics.cpp b/examples/pipelinestatistics/pipelinestatistics.cpp deleted file mode 100644 index 216f1d47..00000000 --- a/examples/pipelinestatistics/pipelinestatistics.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/* -* Vulkan Example - Retrieving pipeline statistics -* -* Copyright (C) 2017-2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - // This sample lets you select between different models to display - struct Models { - std::vector objects; - int32_t objectIndex{ 3 }; - std::vector names; - } models; - // Size for the two-dimensional grid of objects (e.g. 3 = draws 3x3 objects) - int32_t gridSize{ 3 }; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelview; - glm::vec4 lightPos{ -10.0f, -10.0f, 10.0f, 1.0f }; - } uniformData; - vks::Buffer uniformBuffer; - - int32_t cullMode{ VK_CULL_MODE_BACK_BIT }; - bool blending{ false }; - bool discard{ false }; - bool wireframe{ false }; - bool tessellation{ false }; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VkQueryPool queryPool{ VK_NULL_HANDLE }; - - // Vector for storing pipeline statistics results - std::vector pipelineStats{}; - std::vector pipelineStatNames{}; - - VulkanExample() : VulkanExampleBase() - { - title = "Pipeline statistics"; - camera.type = Camera::CameraType::firstperson; - camera.setPosition(glm::vec3(-3.0f, 1.0f, -2.75f)); - camera.setRotation(glm::vec3(-15.25f, -46.5f, 0.0f)); - camera.movementSpeed = 4.0f; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - camera.rotationSpeed = 0.25f; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyQueryPool(device, queryPool, nullptr); - uniformBuffer.destroy(); - } - } - - virtual void getEnabledFeatures() - { - // Support for pipeline statistics is optional - if (deviceFeatures.pipelineStatisticsQuery) { - enabledFeatures.pipelineStatisticsQuery = VK_TRUE; - } - else { - vks::tools::exitFatal("Selected GPU does not support pipeline statistics!", VK_ERROR_FEATURE_NOT_PRESENT); - } - if (deviceFeatures.fillModeNonSolid) { - enabledFeatures.fillModeNonSolid = VK_TRUE; - } - if (deviceFeatures.tessellationShader) { - enabledFeatures.tessellationShader = VK_TRUE; - } - } - - // Setup a query pool for storing pipeline statistics - void setupQueryPool() - { - pipelineStatNames = { - "Input assembly vertex count ", - "Input assembly primitives count ", - "Vertex shader invocations ", - "Clipping stage primitives processed", - "Clipping stage primitives output ", - "Fragment shader invocations " - }; - if (deviceFeatures.tessellationShader) { - pipelineStatNames.push_back("Tess. control shader patches "); - pipelineStatNames.push_back("Tess. eval. shader invocations "); - } - pipelineStats.resize(pipelineStatNames.size()); - - VkQueryPoolCreateInfo queryPoolInfo = {}; - queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - // This query pool will store pipeline statistics - queryPoolInfo.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS; - // Pipeline counters to be returned for this pool - queryPoolInfo.pipelineStatistics = - VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT | - VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT | - VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | - VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT | - VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT | - VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT; - if (deviceFeatures.tessellationShader) { - queryPoolInfo.pipelineStatistics |= - VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT | - VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT; - } - queryPoolInfo.queryCount = 1; - VK_CHECK_RESULT(vkCreateQueryPool(device, &queryPoolInfo, NULL, &queryPool)); - } - - // Retrieves the results of the pipeline statistics query submitted to the command buffer - void getQueryResults() - { - // The size of the data we want to fetch ist based on the count of statistics values - uint32_t dataSize = static_cast(pipelineStats.size()) * sizeof(uint64_t); - // The stride between queries is the no. of unique value entries - uint32_t stride = static_cast(pipelineStatNames.size()) * sizeof(uint64_t); - // Note: for one query both values have the same size, but to make it easier to expand this sample these are properly calculated - vkGetQueryPoolResults( - device, - queryPool, - 0, - 1, - dataSize, - pipelineStats.data(), - stride, - VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Reset timestamp query pool - vkCmdResetQueryPool(drawCmdBuffers[i], queryPool, 0, 1); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - - // Start capture of pipeline statistics - vkCmdBeginQuery(drawCmdBuffers[i], queryPool, 0, 0); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &models.objects[models.objectIndex].vertices.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], models.objects[models.objectIndex].indices.buffer, 0, VK_INDEX_TYPE_UINT32); - - for (int32_t y = 0; y < gridSize; y++) { - for (int32_t x = 0; x < gridSize; x++) { - glm::vec3 pos = glm::vec3(float(x - (gridSize / 2.0f)) * 2.5f, 0.0f, float(y - (gridSize / 2.0f)) * 2.5f); - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::vec3), &pos); - models.objects[models.objectIndex].draw(drawCmdBuffers[i]); - } - } - - // End capture of pipeline statistics - vkCmdEndQuery(drawCmdBuffers[i], queryPool, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - // Objects - std::vector filenames = { "sphere.gltf", "teapot.gltf", "torusknot.gltf", "venus.gltf" }; - models.names = { "Sphere", "Teapot", "Torusknot", "Venus" }; - models.objects.resize(filenames.size()); - for (size_t i = 0; i < filenames.size(); i++) { - models.objects[i].loadFromFile(getAssetPath() + "models/" + filenames[i], vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - } - - void preparePipelines() - { - // Layout - if (pipelineLayout == VK_NULL_HANDLE) { - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::vec3), 0); - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - } - - // Pipeline - if (pipeline != VK_NULL_HANDLE) { - // Destroy old pipeline if we're going to recreate it - vkDestroyPipeline(device, pipeline, nullptr); - } - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, cullMode, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); - VkPipelineTessellationStateCreateInfo tessellationState = vks::initializers::pipelineTessellationStateCreateInfo(3); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color }); - - if (blending) { - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - depthStencilState.depthWriteEnable = VK_FALSE; - } - - if (discard) { - rasterizationState.rasterizerDiscardEnable = VK_TRUE; - } - - if (wireframe) { - rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; - } - - std::vector shaderStages{}; - shaderStages.push_back(loadShader(getShadersPath() + "pipelinestatistics/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT)); - if (!discard) { - // When discard is enabled a pipeline must not contain a fragment shader - shaderStages.push_back(loadShader(getShadersPath() + "pipelinestatistics/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT)); - } - - if (tessellation) { - inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; - pipelineCI.pTessellationState = &tessellationState; - shaderStages.push_back(loadShader(getShadersPath() + "pipelinestatistics/scene.tesc.spv", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)); - shaderStages.push_back(loadShader(getShadersPath() + "pipelinestatistics/scene.tese.spv", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)); - } - - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelview = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - setupQueryPool(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - - // Read query results for displaying in next frame - getQueryResults(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->comboBox("Object type", &models.objectIndex, models.names)) { - updateUniformBuffers(); - buildCommandBuffers(); - } - if (overlay->sliderInt("Grid size", &gridSize, 1, 10)) { - buildCommandBuffers(); - } - // To avoid having to create pipelines for all the settings up front, we recreate a single pipelin with different settings instead - bool recreatePipeline{ false }; - std::vector cullModeNames = { "None", "Front", "Back", "Back and front" }; - recreatePipeline |= overlay->comboBox("Cull mode", &cullMode, cullModeNames); - recreatePipeline |= overlay->checkBox("Blending", &blending); - recreatePipeline |= overlay->checkBox("Discard", &discard); - // These features may not be supported by all implementations - if (deviceFeatures.fillModeNonSolid) { - recreatePipeline |= overlay->checkBox("Wireframe", &wireframe); - } - if (deviceFeatures.tessellationShader) { - recreatePipeline |= overlay->checkBox("Tessellation", &tessellation); - } - if (recreatePipeline) { - preparePipelines(); - buildCommandBuffers(); - } - } - if (!pipelineStats.empty()) { - if (overlay->header("Pipeline statistics")) { - for (auto i = 0; i < pipelineStats.size(); i++) { - std::string caption = pipelineStatNames[i] + ": %d"; - overlay->text(caption.c_str(), pipelineStats[i]); - } - } - } - } - -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/pushconstants/pushconstants.cpp b/examples/pushconstants/pushconstants.cpp deleted file mode 100644 index 58376dfe..00000000 --- a/examples/pushconstants/pushconstants.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* -* Vulkan Example - Push constants example (small shader block accessed outside of uniforms for fast updates) -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -/* -* Summary: -* Using push constants it's possible to pass a small bit of static data to a shader, which is stored in the command buffer stat -* This is perfect for passing e.g. static per-object data or parameters without the need for descriptor sets -* The sample uses these to push different static parameters for rendering multiple objects -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - vkglTF::Model model; - - // Color and position data for each sphere is uploaded using push constants - struct SpherePushConstantData { - glm::vec4 color; - glm::vec4 position; - }; - std::array spheres; - - struct UniformData { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Push constants"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -10.0f)); - camera.setRotation(glm::vec3(0.0, 0.0f, 0.0f)); - camera.setPerspective(60.0f, (float) width / (float) height, 0.1f, 256.0f); - camera.setRotationSpeed(0.5f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - void setupSpheres() - { - // Setup random colors and fixed positions for every sphere in the scene - std::random_device rndDevice; - std::default_random_engine rndEngine(benchmark.active ? 0 : rndDevice()); - std::uniform_real_distribution rndDist(0.1f, 1.0f); - for (uint32_t i = 0; i < spheres.size(); i++) { - spheres[i].color = glm::vec4(rndDist(rndEngine), rndDist(rndEngine), rndDist(rndEngine), 1.0f); - const float rad = glm::radians(i * 360.0f / static_cast(spheres.size())); - spheres[i].position = glm::vec4(glm::vec3(sin(rad), cos(rad), 0.0f) * 3.5f, 1.0f); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - // [POI] Render the spheres passing color and position via push constants - uint32_t spherecount = static_cast(spheres.size()); - for (uint32_t j = 0; j < spherecount; j++) { - // [POI] Pass static sphere data as push constants - vkCmdPushConstants( - drawCmdBuffers[i], - pipelineLayout, - VK_SHADER_STAGE_VERTEX_BIT, - 0, - sizeof(SpherePushConstantData), - &spheres[j]); - model.draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - model.loadFromFile(getAssetPath() + "models/sphere.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - - void preparePipelines() - { - // Layout - // [POI] Define the push constant range used by the pipeline layout - // Note that the spec only requires a minimum of 128 bytes, so for passing larger blocks of data you'd use UBOs or SSBOs - VkPushConstantRange pushConstantRange{}; - // Push constants will only be accessible at the selected pipeline stages, for this sample it's the vertex shader that reads them - pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - pushConstantRange.offset = 0; - pushConstantRange.size = sizeof(SpherePushConstantData); - - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); - shaderStages[0] = loadShader(getShadersPath() + "pushconstants/pushconstants.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pushconstants/pushconstants.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f)); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - setupSpheres(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/pushdescriptors/pushdescriptors.cpp b/examples/pushdescriptors/pushdescriptors.cpp deleted file mode 100644 index da2c3e2c..00000000 --- a/examples/pushdescriptors/pushdescriptors.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* -* Vulkan Example - Push descriptors -* -* Note: Requires a device that supports the VK_KHR_push_descriptor extension -* -* Push descriptors apply the push constants concept to descriptor sets. So instead of creating -* per-model descriptor sets (along with a pool for each descriptor type) for rendering multiple objects, -* this example uses push descriptors to pass descriptor sets for per-model textures and matrices -* at command buffer creation time. -* -* Copyright (C) 2018-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool animate = true; - - PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR{ VK_NULL_HANDLE }; - VkPhysicalDevicePushDescriptorPropertiesKHR pushDescriptorProps{}; - - struct Cube { - vks::Texture2D texture; - vks::Buffer uniformBuffer; - glm::vec3 rotation; - glm::mat4 modelMat; - }; - std::array cubes; - - vkglTF::Model model; - - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Push descriptors"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -5.0f)); - // Enable extension required for push descriptors - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - for (auto cube : cubes) { - cube.uniformBuffer.destroy(); - cube.texture.destroy(); - } - uniformBuffer.destroy(); - } - } - - virtual void getEnabledFeatures() - { - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - }; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - model.bindBuffers(drawCmdBuffers[i]); - - // Render two cubes using different descriptor sets using push descriptors - for (const auto& cube : cubes) { - - // Instead of preparing the descriptor sets up-front, using push descriptors we can set (push) them inside of a command buffer - // This allows a more dynamic approach without the need to create descriptor sets for each model - // Note: dstSet for each descriptor set write is left at zero as this is ignored when using push descriptors - - std::array writeDescriptorSets{}; - - // Scene matrices - writeDescriptorSets[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSets[0].dstSet = 0; - writeDescriptorSets[0].dstBinding = 0; - writeDescriptorSets[0].descriptorCount = 1; - writeDescriptorSets[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - writeDescriptorSets[0].pBufferInfo = &uniformBuffer.descriptor; - - // Model matrices - writeDescriptorSets[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSets[1].dstSet = 0; - writeDescriptorSets[1].dstBinding = 1; - writeDescriptorSets[1].descriptorCount = 1; - writeDescriptorSets[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - writeDescriptorSets[1].pBufferInfo = &cube.uniformBuffer.descriptor; - - // Texture - writeDescriptorSets[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSets[2].dstSet = 0; - writeDescriptorSets[2].dstBinding = 2; - writeDescriptorSets[2].descriptorCount = 1; - writeDescriptorSets[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSets[2].pImageInfo = &cube.texture.descriptor; - - vkCmdPushDescriptorSetKHR(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 3, writeDescriptorSets.data()); - - model.draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - model.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - cubes[0].texture.loadFromFile(getAssetPath() + "textures/crate01_color_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - cubes[1].texture.loadFromFile(getAssetPath() + "textures/crate02_color_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void setupDescriptorSetLayout() - { - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 1), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - }; - - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI{}; - descriptorLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - // Setting this flag tells the descriptor set layouts that no actual descriptor sets are allocated but instead pushed at command buffer creation time - descriptorLayoutCI.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; - descriptorLayoutCI.bindingCount = static_cast(setLayoutBindings.size()); - descriptorLayoutCI.pBindings = setLayoutBindings.data(); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayout)); - - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color}); - - shaderStages[0] = loadShader(getShadersPath() + "pushdescriptors/cube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "pushdescriptors/cube.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareUniformBuffers() - { - // Vertex shader scene uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - - // Vertex shader cube model uniform buffer blocks - for (auto& cube : cubes) { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &cube.uniformBuffer, sizeof(glm::mat4))); - VK_CHECK_RESULT(cube.uniformBuffer.map()); - } - - updateUniformBuffers(); - updateCubeUniformBuffers(); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void updateCubeUniformBuffers() - { - cubes[0].modelMat = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 0.0f, 0.0f)); - cubes[1].modelMat = glm::translate(glm::mat4(1.0f), glm::vec3( 1.5f, 0.5f, 0.0f)); - - for (auto& cube : cubes) { - cube.modelMat = glm::rotate(cube.modelMat, glm::radians(cube.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); - cube.modelMat = glm::rotate(cube.modelMat, glm::radians(cube.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - cube.modelMat = glm::rotate(cube.modelMat, glm::radians(cube.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); - cube.modelMat = glm::scale(cube.modelMat, glm::vec3(0.25f)); - memcpy(cube.uniformBuffer.mapped, &cube.modelMat, sizeof(glm::mat4)); - } - - if (animate && !paused) { - cubes[0].rotation.x += 2.5f * frameTimer; - if (cubes[0].rotation.x > 360.0f) - cubes[0].rotation.x -= 360.0f; - cubes[1].rotation.y += 2.0f * frameTimer; - if (cubes[1].rotation.y > 360.0f) - cubes[1].rotation.y -= 360.0f; - } - } - - void prepare() - { - VulkanExampleBase::prepare(); - - /* - Extension specific functions - */ - - // The push descriptor update function is part of an extension so it has to be manually loaded - vkCmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)vkGetDeviceProcAddr(device, "vkCmdPushDescriptorSetKHR"); - if (!vkCmdPushDescriptorSetKHR) { - vks::tools::exitFatal("Could not get a valid function pointer for vkCmdPushDescriptorSetKHR", -1); - } - - // Get device push descriptor properties (to display them) - PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR")); - if (!vkGetPhysicalDeviceProperties2KHR) { - vks::tools::exitFatal("Could not get a valid function pointer for vkGetPhysicalDeviceProperties2KHR", -1); - } - VkPhysicalDeviceProperties2KHR deviceProps2{}; - pushDescriptorProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR; - deviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; - deviceProps2.pNext = &pushDescriptorProps; - vkGetPhysicalDeviceProperties2KHR(physicalDevice, &deviceProps2); - - /* - End of extension specific functions - */ - - loadAssets(); - prepareUniformBuffers(); - setupDescriptorSetLayout(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - if (animate && !paused) { - updateCubeUniformBuffers(); - } - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->checkBox("Animate", &animate); - } - if (overlay->header("Device properties")) { - overlay->text("maxPushDescriptors: %d", pushDescriptorProps.maxPushDescriptors); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/radialblur/radialblur.cpp b/examples/radialblur/radialblur.cpp deleted file mode 100644 index bf59b794..00000000 --- a/examples/radialblur/radialblur.cpp +++ /dev/null @@ -1,614 +0,0 @@ -/* -* Vulkan Example - Fullscreen radial blur (Single pass offscreen effect) -* -* This samples shows how to implement a simple post-processing effect -* -* Copyright (C) 2016-2024 Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool blur = true; - bool displayTexture = false; - - vks::Texture2D gradientTexture; - vkglTF::Model scene; - - struct UniformDataScene { - glm::mat4 projection; - glm::mat4 modelView; - float gradientPos = 0.0f; - } uniformDataScene; - - struct UniformDataBlurParams { - float radialBlurScale = 0.35f; - float radialBlurStrength = 0.75f; - glm::vec2 radialOrigin = glm::vec2(0.5f, 0.5f); - } uniformDataBlurParams; - - struct { - vks::Buffer scene; - vks::Buffer blurParams; - } uniformBuffers; - - struct { - VkPipeline radialBlur{ VK_NULL_HANDLE }; - VkPipeline colorPass{ VK_NULL_HANDLE }; - VkPipeline phongPass{ VK_NULL_HANDLE }; - VkPipeline offscreenDisplay{ VK_NULL_HANDLE }; - } pipelines; - - struct { - VkPipelineLayout radialBlur{ VK_NULL_HANDLE }; - VkPipelineLayout scene{ VK_NULL_HANDLE }; - } pipelineLayouts; - - struct { - VkDescriptorSet scene{ VK_NULL_HANDLE }; - VkDescriptorSet radialBlur{ VK_NULL_HANDLE }; - } descriptorSets; - - struct { - VkDescriptorSetLayout scene{ VK_NULL_HANDLE }; - VkDescriptorSetLayout radialBlur{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - // Framebuffer for offscreen rendering - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory mem; - VkImageView view; - }; - struct OffscreenPass { - int32_t width, height; - VkFramebuffer frameBuffer; - FrameBufferAttachment color, depth; - VkRenderPass renderPass; - VkSampler sampler; - VkDescriptorImageInfo descriptor; - } offscreenPass{}; - - // Size of the shadow map texture (per face) - const uint32_t offscreenImageSize{ 512 }; - // We use an 8 bit per component RGBA offscreen image for storing the scene parts that will be blurred - const VkFormat offscreenImageFormat{ VK_FORMAT_R8G8B8A8_UNORM }; - - VulkanExample() : VulkanExampleBase() - { - title = "Full screen radial blur effect"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -17.5f)); - camera.setRotation(glm::vec3(-16.25f, -28.75f, 0.0f)); - camera.setPerspective(45.0f, (float)width / (float)height, 1.0f, 256.0f); - timerSpeed *= 0.5f; - } - - ~VulkanExample() - { - if (device) { - // Frame buffer - - // Color attachment - vkDestroyImageView(device, offscreenPass.color.view, nullptr); - vkDestroyImage(device, offscreenPass.color.image, nullptr); - vkFreeMemory(device, offscreenPass.color.mem, nullptr); - - // Depth attachment - vkDestroyImageView(device, offscreenPass.depth.view, nullptr); - vkDestroyImage(device, offscreenPass.depth.image, nullptr); - vkFreeMemory(device, offscreenPass.depth.mem, nullptr); - - vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); - vkDestroySampler(device, offscreenPass.sampler, nullptr); - vkDestroyFramebuffer(device, offscreenPass.frameBuffer, nullptr); - - vkDestroyPipeline(device, pipelines.radialBlur, nullptr); - vkDestroyPipeline(device, pipelines.phongPass, nullptr); - vkDestroyPipeline(device, pipelines.colorPass, nullptr); - vkDestroyPipeline(device, pipelines.offscreenDisplay, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayouts.radialBlur, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.scene, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.scene, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.radialBlur, nullptr); - - uniformBuffers.scene.destroy(); - uniformBuffers.blurParams.destroy(); - - gradientTexture.destroy(); - } - } - - // Setup the offscreen framebuffer for rendering the blurred scene - // The color attachment of this framebuffer will then be used to sample frame in the fragment shader of the final pass - void prepareOffscreen() - { - offscreenPass.width = offscreenImageSize; - offscreenPass.height = offscreenImageSize; - - // Find a suitable depth format - VkFormat fbDepthFormat; - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat); - assert(validDepthFormat); - - // Color attachment - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = offscreenImageFormat; - image.extent.width = offscreenPass.width; - image.extent.height = offscreenPass.height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - // We will sample directly from the color attachment - image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.color.image)); - vkGetImageMemoryRequirements(device, offscreenPass.color.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.color.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.color.image, offscreenPass.color.mem, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = offscreenImageFormat; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = offscreenPass.color.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreenPass.color.view)); - - // Create sampler to sample from the attachment in the fragment shader - VkSamplerCreateInfo samplerInfo = vks::initializers::samplerCreateInfo(); - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = samplerInfo.addressModeU; - samplerInfo.addressModeW = samplerInfo.addressModeU; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.maxAnisotropy = 1.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 1.0f; - samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &offscreenPass.sampler)); - - // Depth stencil attachment - image.format = fbDepthFormat; - image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.depth.image)); - vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0)); - - VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo(); - depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilView.format = fbDepthFormat; - depthStencilView.flags = 0; - depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (fbDepthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) - depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - depthStencilView.subresourceRange.baseMipLevel = 0; - depthStencilView.subresourceRange.levelCount = 1; - depthStencilView.subresourceRange.baseArrayLayer = 0; - depthStencilView.subresourceRange.layerCount = 1; - depthStencilView.image = offscreenPass.depth.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view)); - - // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering - - std::array attchmentDescriptions = {}; - // Color attachment - attchmentDescriptions[0].format = offscreenImageFormat; - attchmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attchmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // Depth attachment - attchmentDescriptions[1].format = fbDepthFormat; - attchmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - VkAttachmentReference depthReference = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - subpassDescription.pDepthStencilAttachment = &depthReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Create the actual renderpass - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attchmentDescriptions.size()); - renderPassInfo.pAttachments = attchmentDescriptions.data(); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpassDescription; - renderPassInfo.dependencyCount = static_cast(dependencies.size()); - renderPassInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &offscreenPass.renderPass)); - - VkImageView attachments[2]; - attachments[0] = offscreenPass.color.view; - attachments[1] = offscreenPass.depth.view; - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = offscreenPass.renderPass; - fbufCreateInfo.attachmentCount = 2; - fbufCreateInfo.pAttachments = attachments; - fbufCreateInfo.width = offscreenPass.width; - fbufCreateInfo.height = offscreenPass.height; - fbufCreateInfo.layers = 1; - - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreenPass.frameBuffer)); - - // Fill a descriptor for later use in a descriptor set - offscreenPass.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - offscreenPass.descriptor.imageView = offscreenPass.color.view; - offscreenPass.descriptor.sampler = offscreenPass.sampler; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - VkViewport viewport; - VkRect2D scissor; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - First render pass: Offscreen rendering - */ - { - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = offscreenPass.renderPass; - renderPassBeginInfo.framebuffer = offscreenPass.frameBuffer; - renderPassBeginInfo.renderArea.extent.width = offscreenPass.width; - renderPassBeginInfo.renderArea.extent.height = offscreenPass.height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - viewport = vks::initializers::viewport((float)offscreenPass.width, (float)offscreenPass.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - scissor = vks::initializers::rect2D(offscreenPass.width, offscreenPass.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.colorPass); - scene.draw(drawCmdBuffers[i]); - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Second render pass: Scene rendering with applied radial blur - */ - { - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // 3D scene - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phongPass); - scene.draw(drawCmdBuffers[i]); - - // Fullscreen triangle (clipped to a quad) with radial blur - if (blur) - { - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.radialBlur, 0, 1, &descriptorSets.radialBlur, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, (displayTexture) ? pipelines.offscreenDisplay : pipelines.radialBlur); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - scene.loadFromFile(getAssetPath() + "models/glowsphere.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY); - gradientTexture.loadFromFile(getAssetPath() + "textures/particle_gradient_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layouts - std::vector setLayoutBindings; - VkDescriptorSetLayoutCreateInfo descriptorLayout; - - // Scene rendering - setLayoutBindings = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1: Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 2: Fragment shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2) - }; - descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.scene)); - - // Fullscreen radial blur - setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // Binding 1: Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.radialBlur)); - - // Sets - VkDescriptorSetAllocateInfo descriptorSetAllocInfo; - - // Scene rendering - descriptorSetAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.scene, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.scene)); - - std::vector offScreenWriteDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor), - // Binding 1: Color gradient sampler - vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &gradientTexture.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(offScreenWriteDescriptorSets.size()), offScreenWriteDescriptorSets.data(), 0, nullptr); - - // Fullscreen radial blur - descriptorSetAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.radialBlur, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.radialBlur)); - - std::vector writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.radialBlur, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.blurParams.descriptor), - // Binding 1: Fragment shader texture sampler - vks::initializers::writeDescriptorSet(descriptorSets.radialBlur, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &offscreenPass.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layouts - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.scene, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.scene)); - - pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.radialBlur, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.radialBlur)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.radialBlur, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Radial blur pipeline - shaderStages[0] = loadShader(getShadersPath() + "radialblur/radialblur.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "radialblur/radialblur.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Empty vertex input state (the vertex shader generates a screen covering triangle) - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCI.pVertexInputState = &emptyInputState; - pipelineCI.layout = pipelineLayouts.radialBlur; - // Additive blending - blendAttachmentState.colorWriteMask = 0xF; - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.radialBlur)); - - // No blending (for debug display) - blendAttachmentState.blendEnable = VK_FALSE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.offscreenDisplay)); - - // Phong pass - pipelineCI.layout = pipelineLayouts.scene; - shaderStages[0] = loadShader(getShadersPath() + "radialblur/phongpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "radialblur/phongpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - blendAttachmentState.blendEnable = VK_FALSE; - depthStencilStateCI.depthWriteEnable = VK_TRUE; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal });; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.phongPass)); - - // Color only pass (offscreen blur base) - shaderStages[0] = loadShader(getShadersPath() + "radialblur/colorpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "radialblur/colorpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - pipelineCI.renderPass = offscreenPass.renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.colorPass)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Phong and color pass vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.scene, sizeof(UniformDataScene))); - // Fullscreen radial blur parameters - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.blurParams, sizeof(UniformDataBlurParams), &uniformDataBlurParams)); - // Map persistent - VK_CHECK_RESULT(uniformBuffers.scene.map()); - VK_CHECK_RESULT(uniformBuffers.blurParams.map()); - } - - // Update parameters for the radial blur pass - // This only does the copy, actual parameters are set via the UI - void updateUniformBuffersBlurParams() - { - memcpy(uniformBuffers.blurParams.mapped, &uniformDataBlurParams, sizeof(UniformDataBlurParams)); - } - - // Update uniform buffers for rendering the 3D scene - void updateUniformBuffers() - { - uniformDataScene.projection = glm::perspective(glm::radians(45.0f), (float)width / (float)height, 1.0f, 256.0f); - camera.setRotation(camera.rotation + glm::vec3(0.0f, frameTimer * 10.0f, 0.0f)); - uniformDataScene.projection = camera.matrices.perspective; - uniformDataScene.modelView = camera.matrices.view; - // Add some animation to the post processing effect by moving through a color gradient for the radial blur - if (!paused) { - uniformDataScene.gradientPos += frameTimer * 0.1f; - } - memcpy(uniformBuffers.scene.mapped, &uniformDataScene, sizeof(UniformDataScene)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareOffscreen(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->checkBox("Radial blur", &blur)) { - buildCommandBuffers(); - } - if (overlay->checkBox("Display render target only", &displayTexture)) { - buildCommandBuffers(); - } - if (blur) { - if (overlay->header("Blur parameters")) { - bool updateParams = false; - updateParams |= overlay->sliderFloat("Scale", &uniformDataBlurParams.radialBlurScale, 0.1f, 1.0f); - updateParams |= overlay->sliderFloat("Strength", &uniformDataBlurParams.radialBlurStrength, 0.1f, 2.0f); - updateParams |= overlay->sliderFloat("Horiz. origin", &uniformDataBlurParams.radialOrigin.x, 0.0f, 1.0f); - updateParams |= overlay->sliderFloat("Vert. origin", &uniformDataBlurParams.radialOrigin.y, 0.0f, 1.0f); - if (updateParams) { - updateUniformBuffersBlurParams(); - } - } - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/rayquery/rayquery.cpp b/examples/rayquery/rayquery.cpp deleted file mode 100644 index 8e0e3269..00000000 --- a/examples/rayquery/rayquery.cpp +++ /dev/null @@ -1,468 +0,0 @@ -/* -* Vulkan Example - Using ray queries for hardware accelerated ray tracing -* -* Ray queries (aka inline ray tracing) can be used in non-raytracing shaders. This sample makes use of that by -* doing ray traced shadows in a fragment shader -* -* Copyright (C) 2020-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" -#include "VulkanRaytracingSample.h" - -class VulkanExample : public VulkanRaytracingSample -{ -public: - glm::vec3 lightPos = glm::vec3(); - - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - glm::vec3 lightPos; - } uniformData; - vks::Buffer uniformBuffer; - - vkglTF::Model scene; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanRaytracingSample::AccelerationStructure bottomLevelAS{}; - VulkanRaytracingSample::AccelerationStructure topLevelAS{}; - - VkPhysicalDeviceRayQueryFeaturesKHR enabledRayQueryFeatures{}; - - VulkanExample() : VulkanRaytracingSample() - { - title = "Ray queries for ray traced shadows"; - camera.type = Camera::CameraType::lookat; - timerSpeed *= 0.25f; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 3.0f, -10.0f)); - rayQueryOnly = true; - enableExtensions(); - enabledDeviceExtensions.push_back(VK_KHR_RAY_QUERY_EXTENSION_NAME); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - deleteAccelerationStructure(bottomLevelAS); - deleteAccelerationStructure(topLevelAS); - } - } - - /* - Create the bottom level acceleration structure contains the scene's actual geometry (vertices, triangles) - */ - void createBottomLevelAccelerationStructure() - { - VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{}; - - vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.vertices.buffer); - indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.indices.buffer); - - uint32_t numTriangles = static_cast(scene.indices.count) / 3; - - // Build - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; - accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.maxVertex = scene.vertices.count - 1; - accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(vkglTF::Vertex); - accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; - accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0; - accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &numTriangles, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(bottomLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the bottom level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = numTriangles; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - } - - /* - The top level acceleration structure contains the scene's object instances - */ - void createTopLevelAccelerationStructure() - { - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f }; - - VkAccelerationStructureInstanceKHR instance{}; - instance.transform = transformMatrix; - instance.instanceCustomIndex = 0; - instance.mask = 0xFF; - instance.instanceShaderBindingTableRecordOffset = 0; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = bottomLevelAS.deviceAddress; - - // Buffer for instance data - vks::Buffer instancesBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &instancesBuffer, - sizeof(VkAccelerationStructureInstanceKHR), - &instance)); - - VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{}; - instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer); - - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE; - accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - uint32_t primitive_count = 1; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &primitive_count, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(topLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the top level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = 1; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - instancesBuffer.destroy(); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - VkViewport viewport; - VkRect2D scissor; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Second pass: Scene rendering with applied shadow map - */ - - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 1.0f } };; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // 3D scene - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - scene.draw(drawCmdBuffers[i]); - - VulkanExampleBase::drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - vkglTF::memoryPropertyFlags = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - scene.loadFromFile(getAssetPath() + "models/vulkanscene_shadow.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1: Acceleration structure - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - std::vector writeDescriptorSets; - - // Debug display - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Scene rendering with shadow map applied - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor) - }; - - // The fragment needs access to the ray tracing acceleration structure, so we pass it as a descriptor - - // As this isn't part of Vulkan's core, we need to pass this informationen via pNext chaining - VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks::initializers::writeDescriptorSetAccelerationStructureKHR(); - descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle; - - VkWriteDescriptorSet accelerationStructureWrite{}; - accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - // The specialized acceleration structure descriptor has to be chained - accelerationStructureWrite.pNext = &descriptorAccelerationStructureInfo; - accelerationStructureWrite.dstSet = descriptorSet; - accelerationStructureWrite.dstBinding = 1; - accelerationStructureWrite.descriptorCount = 1; - accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - - writeDescriptorSets.push_back(accelerationStructureWrite); - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Scene rendering with ray traced shadows applied - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal }); - rasterizationStateCI.cullMode = VK_CULL_MODE_BACK_BIT; - shaderStages[0] = loadShader(getShadersPath() + "rayquery/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "rayquery/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Scene vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffer, - sizeof(UniformData))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - - updateLight(); - updateUniformBuffers(); - } - - void updateLight() - { - // Animate the light source - lightPos.x = cos(glm::radians(timer * 360.0f)) * 40.0f; - lightPos.y = -50.0f + sin(glm::radians(timer * 360.0f)) * 20.0f; - lightPos.z = 25.0f + sin(glm::radians(timer * 360.0f)) * 5.0f; - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.model = glm::mat4(1.0f); - uniformData.lightPos = lightPos; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void getEnabledFeatures() - { - // Enable features required for ray tracing using feature chaining via pNext - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE; - enabledAccelerationStructureFeatures.pNext = &enabledBufferDeviceAddresFeatures; - - enabledRayQueryFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR; - enabledRayQueryFeatures.rayQuery = VK_TRUE; - enabledRayQueryFeatures.pNext = &enabledAccelerationStructureFeatures; - - deviceCreatepNextChain = &enabledRayQueryFeatures; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanRaytracingSample::prepare(); - loadAssets(); - prepareUniformBuffers(); - createBottomLevelAccelerationStructure(); - createTopLevelAccelerationStructure(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - if (!paused || camera.updated) { - updateLight(); - } - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/raytracingbasic/raytracingbasic.cpp b/examples/raytracingbasic/raytracingbasic.cpp deleted file mode 100644 index d67f4c15..00000000 --- a/examples/raytracingbasic/raytracingbasic.cpp +++ /dev/null @@ -1,909 +0,0 @@ -/* -* Vulkan Example - Basic hardware accelerated ray tracing example -* -* Copyright (C) 2019-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -// Holds data for a ray tracing scratch buffer that is used as a temporary storage -struct RayTracingScratchBuffer -{ - uint64_t deviceAddress = 0; - VkBuffer handle = VK_NULL_HANDLE; - VkDeviceMemory memory = VK_NULL_HANDLE; -}; - -// Ray tracing acceleration structure -struct AccelerationStructure { - VkAccelerationStructureKHR handle; - uint64_t deviceAddress = 0; - VkDeviceMemory memory; - VkBuffer buffer; -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; - PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR; - PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR; - PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR; - PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; - PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR; - PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR; - PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR; - PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR; - PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR; - - VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingPipelineProperties{}; - VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeatures{}; - - VkPhysicalDeviceBufferDeviceAddressFeatures enabledBufferDeviceAddresFeatures{}; - VkPhysicalDeviceRayTracingPipelineFeaturesKHR enabledRayTracingPipelineFeatures{}; - VkPhysicalDeviceAccelerationStructureFeaturesKHR enabledAccelerationStructureFeatures{}; - - AccelerationStructure bottomLevelAS{}; - AccelerationStructure topLevelAS{}; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount; - vks::Buffer transformBuffer; - std::vector shaderGroups{}; - vks::Buffer raygenShaderBindingTable; - vks::Buffer missShaderBindingTable; - vks::Buffer hitShaderBindingTable; - - struct StorageImage { - VkDeviceMemory memory; - VkImage image; - VkImageView view; - VkFormat format; - } storageImage; - - struct UniformData { - glm::mat4 viewInverse; - glm::mat4 projInverse; - } uniformData; - vks::Buffer ubo; - - VkPipeline pipeline; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; - - VulkanExample() : VulkanExampleBase() - { - title = "Ray tracing basic"; - settings.overlay = false; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -2.5f)); - - // Require Vulkan 1.1 - apiVersion = VK_API_VERSION_1_1; - - // Ray tracing related extensions required by this sample - enabledDeviceExtensions.push_back(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME); - - // Required by VK_KHR_acceleration_structure - enabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - - // Required for VK_KHR_ray_tracing_pipeline - enabledDeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); - - // Required by VK_KHR_spirv_1_4 - enabledDeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); - } - - ~VulkanExample() - { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyImageView(device, storageImage.view, nullptr); - vkDestroyImage(device, storageImage.image, nullptr); - vkFreeMemory(device, storageImage.memory, nullptr); - vkFreeMemory(device, bottomLevelAS.memory, nullptr); - vkDestroyBuffer(device, bottomLevelAS.buffer, nullptr); - vkDestroyAccelerationStructureKHR(device, bottomLevelAS.handle, nullptr); - vkFreeMemory(device, topLevelAS.memory, nullptr); - vkDestroyBuffer(device, topLevelAS.buffer, nullptr); - vkDestroyAccelerationStructureKHR(device, topLevelAS.handle, nullptr); - vertexBuffer.destroy(); - indexBuffer.destroy(); - transformBuffer.destroy(); - raygenShaderBindingTable.destroy(); - missShaderBindingTable.destroy(); - hitShaderBindingTable.destroy(); - ubo.destroy(); - } - - /* - Create a scratch buffer to hold temporary data for a ray tracing acceleration structure - */ - RayTracingScratchBuffer createScratchBuffer(VkDeviceSize size) - { - RayTracingScratchBuffer scratchBuffer{}; - - VkBufferCreateInfo bufferCreateInfo{}; - bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferCreateInfo.size = size; - bufferCreateInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &scratchBuffer.handle)); - - VkMemoryRequirements memoryRequirements{}; - vkGetBufferMemoryRequirements(device, scratchBuffer.handle, &memoryRequirements); - - VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{}; - memoryAllocateFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; - memoryAllocateFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; - - VkMemoryAllocateInfo memoryAllocateInfo = {}; - memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memoryAllocateInfo.pNext = &memoryAllocateFlagsInfo; - memoryAllocateInfo.allocationSize = memoryRequirements.size; - memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &scratchBuffer.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, scratchBuffer.handle, scratchBuffer.memory, 0)); - - VkBufferDeviceAddressInfoKHR bufferDeviceAddressInfo{}; - bufferDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; - bufferDeviceAddressInfo.buffer = scratchBuffer.handle; - scratchBuffer.deviceAddress = vkGetBufferDeviceAddressKHR(device, &bufferDeviceAddressInfo); - - return scratchBuffer; - } - - void deleteScratchBuffer(RayTracingScratchBuffer& scratchBuffer) - { - if (scratchBuffer.memory != VK_NULL_HANDLE) { - vkFreeMemory(device, scratchBuffer.memory, nullptr); - } - if (scratchBuffer.handle != VK_NULL_HANDLE) { - vkDestroyBuffer(device, scratchBuffer.handle, nullptr); - } - } - - void createAccelerationStructureBuffer(AccelerationStructure &accelerationStructure, VkAccelerationStructureBuildSizesInfoKHR buildSizeInfo) - { - VkBufferCreateInfo bufferCreateInfo{}; - bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferCreateInfo.size = buildSizeInfo.accelerationStructureSize; - bufferCreateInfo.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &accelerationStructure.buffer)); - VkMemoryRequirements memoryRequirements{}; - vkGetBufferMemoryRequirements(device, accelerationStructure.buffer, &memoryRequirements); - VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{}; - memoryAllocateFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; - memoryAllocateFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; - VkMemoryAllocateInfo memoryAllocateInfo{}; - memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memoryAllocateInfo.pNext = &memoryAllocateFlagsInfo; - memoryAllocateInfo.allocationSize = memoryRequirements.size; - memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &accelerationStructure.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, accelerationStructure.buffer, accelerationStructure.memory, 0)); - } - - - /* - Gets the device address from a buffer that's required for some of the buffers used for ray tracing - */ - uint64_t getBufferDeviceAddress(VkBuffer buffer) - { - VkBufferDeviceAddressInfoKHR bufferDeviceAI{}; - bufferDeviceAI.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; - bufferDeviceAI.buffer = buffer; - return vkGetBufferDeviceAddressKHR(device, &bufferDeviceAI); - } - - /* - Set up a storage image that the ray generation shader will be writing to - */ - void createStorageImage() - { - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = swapChain.colorFormat; - image.extent.width = width; - image.extent.height = height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT; - image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &storageImage.image)); - - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, storageImage.image, &memReqs); - VkMemoryAllocateInfo memoryAllocateInfo = vks::initializers::memoryAllocateInfo(); - memoryAllocateInfo.allocationSize = memReqs.size; - memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &storageImage.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, storageImage.image, storageImage.memory, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = swapChain.colorFormat; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = storageImage.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &storageImage.view)); - - VkCommandBuffer cmdBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout(cmdBuffer, storageImage.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_GENERAL, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - vulkanDevice->flushCommandBuffer(cmdBuffer, queue); - } - - /* - Create the bottom level acceleration structure contains the scene's actual geometry (vertices, triangles) - */ - void createBottomLevelAccelerationStructure() - { - // Setup vertices for a single triangle - struct Vertex { - float pos[3]; - }; - std::vector vertices = { - { { 1.0f, 1.0f, 0.0f } }, - { { -1.0f, 1.0f, 0.0f } }, - { { 0.0f, -1.0f, 0.0f } } - }; - - // Setup indices - std::vector indices = { 0, 1, 2 }; - indexCount = static_cast(indices.size()); - - // Setup identity transform matrix - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f - }; - - // Create buffers - // For the sake of simplicity we won't stage the vertex data to the GPU memory - // Vertex buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &vertexBuffer, - vertices.size() * sizeof(Vertex), - vertices.data())); - // Index buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &indexBuffer, - indices.size() * sizeof(uint32_t), - indices.data())); - // Transform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &transformBuffer, - sizeof(VkTransformMatrixKHR), - &transformMatrix)); - - VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR transformBufferDeviceAddress{}; - - vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(vertexBuffer.buffer); - indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(indexBuffer.buffer); - transformBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(transformBuffer.buffer); - - // Build - VkAccelerationStructureGeometryKHR accelerationStructureGeometry{}; - accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; - accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.maxVertex = 2; - accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(Vertex); - accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; - accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0; - accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr; - accelerationStructureGeometry.geometry.triangles.transformData = transformBufferDeviceAddress; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{}; - accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - const uint32_t numTriangles = 1; - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{}; - accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &numTriangles, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructureBuffer(bottomLevelAS, accelerationStructureBuildSizesInfo); - - VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{}; - accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - accelerationStructureCreateInfo.buffer = bottomLevelAS.buffer; - accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize; - accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &bottomLevelAS.handle); - - // Create a small scratch buffer used during build of the bottom level acceleration structure - RayTracingScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{}; - accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = numTriangles; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{}; - accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; - accelerationDeviceAddressInfo.accelerationStructure = bottomLevelAS.handle; - bottomLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo); - - deleteScratchBuffer(scratchBuffer); - } - - /* - The top level acceleration structure contains the scene's object instances - */ - void createTopLevelAccelerationStructure() - { - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f }; - - VkAccelerationStructureInstanceKHR instance{}; - instance.transform = transformMatrix; - instance.instanceCustomIndex = 0; - instance.mask = 0xFF; - instance.instanceShaderBindingTableRecordOffset = 0; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = bottomLevelAS.deviceAddress; - - // Buffer for instance data - vks::Buffer instancesBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &instancesBuffer, - sizeof(VkAccelerationStructureInstanceKHR), - &instance)); - - VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{}; - instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer); - - VkAccelerationStructureGeometryKHR accelerationStructureGeometry{}; - accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE; - accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress; - - // Get size info - /* - The pSrcAccelerationStructure, dstAccelerationStructure, and mode members of pBuildInfo are ignored. Any VkDeviceOrHostAddressKHR members of pBuildInfo are ignored by this command, except that the hostAddress member of VkAccelerationStructureGeometryTrianglesDataKHR::transformData will be examined to check if it is NULL.* - */ - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{}; - accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - uint32_t primitive_count = 1; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{}; - accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &primitive_count, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructureBuffer(topLevelAS, accelerationStructureBuildSizesInfo); - - VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{}; - accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - accelerationStructureCreateInfo.buffer = topLevelAS.buffer; - accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize; - accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &topLevelAS.handle); - - // Create a small scratch buffer used during build of the top level acceleration structure - RayTracingScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{}; - accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = 1; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{}; - accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; - accelerationDeviceAddressInfo.accelerationStructure = topLevelAS.handle; - topLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo); - - deleteScratchBuffer(scratchBuffer); - instancesBuffer.destroy(); - } - - /* - Create the Shader Binding Tables that binds the programs and top-level acceleration structure - - SBT Layout used in this sample: - - /-----------\ - | raygen | - |-----------| - | miss | - |-----------| - | hit | - \-----------/ - - */ - void createShaderBindingTable() { - const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize; - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - const uint32_t groupCount = static_cast(shaderGroups.size()); - const uint32_t sbtSize = groupCount * handleSizeAligned; - - std::vector shaderHandleStorage(sbtSize); - VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data())); - - const VkBufferUsageFlags bufferUsageFlags = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - const VkMemoryPropertyFlags memoryUsageFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - VK_CHECK_RESULT(vulkanDevice->createBuffer(bufferUsageFlags, memoryUsageFlags, &raygenShaderBindingTable, handleSize)); - VK_CHECK_RESULT(vulkanDevice->createBuffer(bufferUsageFlags, memoryUsageFlags, &missShaderBindingTable, handleSize)); - VK_CHECK_RESULT(vulkanDevice->createBuffer(bufferUsageFlags, memoryUsageFlags, &hitShaderBindingTable, handleSize)); - - // Copy handles - raygenShaderBindingTable.map(); - missShaderBindingTable.map(); - hitShaderBindingTable.map(); - memcpy(raygenShaderBindingTable.mapped, shaderHandleStorage.data(), handleSize); - memcpy(missShaderBindingTable.mapped, shaderHandleStorage.data() + handleSizeAligned, handleSize); - memcpy(hitShaderBindingTable.mapped, shaderHandleStorage.data() + handleSizeAligned * 2, handleSize); - } - - /* - Create the descriptor sets used for the ray tracing dispatch - */ - void createDescriptorSets() - { - std::vector poolSizes = { - { VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 } - }; - VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool)); - - VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); - - VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo{}; - descriptorAccelerationStructureInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; - descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle; - - VkWriteDescriptorSet accelerationStructureWrite{}; - accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - // The specialized acceleration structure descriptor has to be chained - accelerationStructureWrite.pNext = &descriptorAccelerationStructureInfo; - accelerationStructureWrite.dstSet = descriptorSet; - accelerationStructureWrite.dstBinding = 0; - accelerationStructureWrite.descriptorCount = 1; - accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - - VkDescriptorImageInfo storageImageDescriptor{}; - storageImageDescriptor.imageView = storageImage.view; - storageImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - VkWriteDescriptorSet uniformBufferWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor); - - std::vector writeDescriptorSets = { - accelerationStructureWrite, - resultImageWrite, - uniformBufferWrite - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE); - } - - /* - Create our ray tracing pipeline - */ - void createRayTracingPipeline() - { - VkDescriptorSetLayoutBinding accelerationStructureLayoutBinding{}; - accelerationStructureLayoutBinding.binding = 0; - accelerationStructureLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - accelerationStructureLayoutBinding.descriptorCount = 1; - accelerationStructureLayoutBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR; - - VkDescriptorSetLayoutBinding resultImageLayoutBinding{}; - resultImageLayoutBinding.binding = 1; - resultImageLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - resultImageLayoutBinding.descriptorCount = 1; - resultImageLayoutBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR; - - VkDescriptorSetLayoutBinding uniformBufferBinding{}; - uniformBufferBinding.binding = 2; - uniformBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - uniformBufferBinding.descriptorCount = 1; - uniformBufferBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR; - - std::vector bindings({ - accelerationStructureLayoutBinding, - resultImageLayoutBinding, - uniformBufferBinding - }); - - VkDescriptorSetLayoutCreateInfo descriptorSetlayoutCI{}; - descriptorSetlayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptorSetlayoutCI.bindingCount = static_cast(bindings.size()); - descriptorSetlayoutCI.pBindings = bindings.data(); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetlayoutCI, nullptr, &descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pipelineLayoutCI{}; - pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutCI.setLayoutCount = 1; - pipelineLayoutCI.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - /* - Setup ray tracing shader groups - */ - std::vector shaderStages; - - // Ray generation group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingbasic/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Miss group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingbasic/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Closest hit group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingbasic/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; - shaderGroup.generalShader = VK_SHADER_UNUSED_KHR; - shaderGroup.closestHitShader = static_cast(shaderStages.size()) - 1; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - /* - Create the ray tracing pipeline - */ - VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI{}; - rayTracingPipelineCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; - rayTracingPipelineCI.stageCount = static_cast(shaderStages.size()); - rayTracingPipelineCI.pStages = shaderStages.data(); - rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size()); - rayTracingPipelineCI.pGroups = shaderGroups.data(); - rayTracingPipelineCI.maxPipelineRayRecursionDepth = 1; - rayTracingPipelineCI.layout = pipelineLayout; - VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline)); - } - - /* - Create the uniform buffer used to pass matrices to the ray tracing ray generation shader - */ - void createUniformBuffer() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &ubo, - sizeof(uniformData), - &uniformData)); - VK_CHECK_RESULT(ubo.map()); - - updateUniformBuffers(); - } - - /* - If the window has been resized, we need to recreate the storage image and it's descriptor - */ - void handleResize() - { - // Delete allocated resources - vkDestroyImageView(device, storageImage.view, nullptr); - vkDestroyImage(device, storageImage.image, nullptr); - vkFreeMemory(device, storageImage.memory, nullptr); - // Recreate image - createStorageImage(); - // Update descriptor - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - vkUpdateDescriptorSets(device, 1, &resultImageWrite, 0, VK_NULL_HANDLE); - resized = false; - } - - /* - Command buffer generation - */ - void buildCommandBuffers() - { - if (resized) - { - handleResize(); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Setup the buffer regions pointing to the shaders in our shader binding table - */ - - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - - VkStridedDeviceAddressRegionKHR raygenShaderSbtEntry{}; - raygenShaderSbtEntry.deviceAddress = getBufferDeviceAddress(raygenShaderBindingTable.buffer); - raygenShaderSbtEntry.stride = handleSizeAligned; - raygenShaderSbtEntry.size = handleSizeAligned; - - VkStridedDeviceAddressRegionKHR missShaderSbtEntry{}; - missShaderSbtEntry.deviceAddress = getBufferDeviceAddress(missShaderBindingTable.buffer); - missShaderSbtEntry.stride = handleSizeAligned; - missShaderSbtEntry.size = handleSizeAligned; - - VkStridedDeviceAddressRegionKHR hitShaderSbtEntry{}; - hitShaderSbtEntry.deviceAddress = getBufferDeviceAddress(hitShaderBindingTable.buffer); - hitShaderSbtEntry.stride = handleSizeAligned; - hitShaderSbtEntry.size = handleSizeAligned; - - VkStridedDeviceAddressRegionKHR callableShaderSbtEntry{}; - - /* - Dispatch the ray tracing commands - */ - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0); - - vkCmdTraceRaysKHR( - drawCmdBuffers[i], - &raygenShaderSbtEntry, - &missShaderSbtEntry, - &hitShaderSbtEntry, - &callableShaderSbtEntry, - width, - height, - 1); - - /* - Copy ray tracing output to swap chain image - */ - - // Prepare current swap chain image as transfer destination - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Prepare ray tracing output image as transfer source - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresourceRange); - - VkImageCopy copyRegion{}; - copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.srcOffset = { 0, 0, 0 }; - copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.dstOffset = { 0, 0, 0 }; - copyRegion.extent = { width, height, 1 }; - vkCmdCopyImage(drawCmdBuffers[i], storageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChain.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - // Transition swap chain image back for presentation - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresourceRange); - - // Transition ray tracing output image back to general layout - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresourceRange); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void updateUniformBuffers() - { - uniformData.projInverse = glm::inverse(camera.matrices.perspective); - uniformData.viewInverse = glm::inverse(camera.matrices.view); - memcpy(ubo.mapped, &uniformData, sizeof(uniformData)); - } - - void getEnabledFeatures() - { - // Enable features required for ray tracing using feature chaining via pNext - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR; - enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE; - enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures; - - enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE; - enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures; - - deviceCreatepNextChain = &enabledAccelerationStructureFeatures; - } - - void prepare() - { - VulkanExampleBase::prepare(); - - // Get ray tracing pipeline properties, which will be used later on in the sample - rayTracingPipelineProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR; - VkPhysicalDeviceProperties2 deviceProperties2{}; - deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - deviceProperties2.pNext = &rayTracingPipelineProperties; - vkGetPhysicalDeviceProperties2(physicalDevice, &deviceProperties2); - - // Get acceleration structure properties, which will be used later on in the sample - accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - VkPhysicalDeviceFeatures2 deviceFeatures2{}; - deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - deviceFeatures2.pNext = &accelerationStructureFeatures; - vkGetPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures2); - - // Get the ray tracing and accelertion structure related function pointers required by this sample - vkGetBufferDeviceAddressKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR")); - vkCmdBuildAccelerationStructuresKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR")); - vkBuildAccelerationStructuresKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR")); - vkCreateAccelerationStructureKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR")); - vkDestroyAccelerationStructureKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR")); - vkGetAccelerationStructureBuildSizesKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureBuildSizesKHR")); - vkGetAccelerationStructureDeviceAddressKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR")); - vkCmdTraceRaysKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR")); - vkGetRayTracingShaderGroupHandlesKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR")); - vkCreateRayTracingPipelinesKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR")); - - // Create the acceleration structures used to render the ray traced scene - createBottomLevelAccelerationStructure(); - createTopLevelAccelerationStructure(); - - createStorageImage(); - createUniformBuffer(); - createRayTracingPipeline(); - createShaderBindingTable(); - createDescriptorSets(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (camera.updated) - updateUniformBuffers(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/raytracingcallable/raytracingcallable.cpp b/examples/raytracingcallable/raytracingcallable.cpp deleted file mode 100644 index ea42641d..00000000 --- a/examples/raytracingcallable/raytracingcallable.cpp +++ /dev/null @@ -1,650 +0,0 @@ -/* -* Vulkan Example - Hardware accelerated ray tracing callable shaders example -* -* Dynamically calls different shaders based on the geometry id in the closest hit shader -* -* Relevant code parts are marked with [POI] -* -* Copyright (C) 2021-2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "VulkanRaytracingSample.h" - -class VulkanExample : public VulkanRaytracingSample -{ -public: - AccelerationStructure bottomLevelAS; - AccelerationStructure topLevelAS; - - std::vector shaderGroups{}; - struct ShaderBindingTables { - ShaderBindingTable raygen; - ShaderBindingTable miss; - ShaderBindingTable hit; - ShaderBindingTable callable; - } shaderBindingTables; - - struct UniformData { - glm::mat4 viewInverse; - glm::mat4 projInverse; - } uniformData; - vks::Buffer ubo; - - VkPipeline pipeline; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - vks::Buffer transformBuffer; - - uint32_t objectCount = 3; - - // This sample is derived from an extended base class that saves most of the ray tracing setup boiler plate - VulkanExample() : VulkanRaytracingSample() - { - title = "Ray tracing callable shaders"; - timerSpeed *= 0.25f; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -10.0f)); - enableExtensions(); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - deleteStorageImage(); - deleteAccelerationStructure(bottomLevelAS); - deleteAccelerationStructure(topLevelAS); - shaderBindingTables.raygen.destroy(); - shaderBindingTables.miss.destroy(); - shaderBindingTables.hit.destroy(); - shaderBindingTables.callable.destroy(); - vertexBuffer.destroy(); - indexBuffer.destroy(); - transformBuffer.destroy(); - ubo.destroy(); - } - } - - /* - Create the bottom level acceleration structure contains the scene's actual geometry (vertices, triangles) - */ - void createBottomLevelAccelerationStructure() - { - // Setup vertices for a single triangle - struct Vertex { - float pos[3]; - }; - std::vector vertices = { - { { 1.0f, 1.0f, 0.0f } }, - { { -1.0f, 1.0f, 0.0f } }, - { { 0.0f, -1.0f, 0.0f } } - }; - - // Setup indices - std::vector indices = { 0, 1, 2 }; - uint32_t indexCount = static_cast(indices.size()); - - // Setup transform matrices for the geometries in the bottom level AS - std::vector transformMatrices(objectCount); - for (uint32_t i = 0; i < objectCount; i++) { - transformMatrices[i] = { - 1.0f, 0.0f, 0.0f, (float)i * 3.0f - 3.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f - }; - } - // Transform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &transformBuffer, - objectCount * sizeof(VkTransformMatrixKHR), - transformMatrices.data())); - - // Create buffers - // For the sake of simplicity we won't stage the vertex data to the GPU memory - // Vertex buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &vertexBuffer, - vertices.size() * sizeof(Vertex), - vertices.data())); - // Index buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &indexBuffer, - indices.size() * sizeof(uint32_t), - indices.data())); - - VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR transformBufferDeviceAddress{}; - - vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(vertexBuffer.buffer); - indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(indexBuffer.buffer); - transformBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(transformBuffer.buffer); - - uint32_t numTriangles = 1; - - // Our scene will consist of three different triangles, that'll be distinguished in the shader via gl_GeometryIndexEXT, so we add three geometries to the bottom level AS - std::vector geometryCounts; - std::vector accelerationStructureGeometries; - for (uint32_t i = 0; i < objectCount; i++) { - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; - accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.maxVertex = 2; - accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(Vertex); - accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; - accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.transformData = transformBufferDeviceAddress; - accelerationStructureGeometries.push_back(accelerationStructureGeometry); - geometryCounts.push_back(1); - } - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = static_cast(accelerationStructureGeometries.size()); - accelerationStructureBuildGeometryInfo.pGeometries = accelerationStructureGeometries.data(); - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - geometryCounts.data(), - &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(bottomLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the bottom level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = static_cast(accelerationStructureGeometries.size()); - accelerationBuildGeometryInfo.pGeometries = accelerationStructureGeometries.data(); - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - // [POI] The bottom level acceleration structure for this sample contains three separate triangle geometries, so we can use gl_GeometryIndexEXT in the closest hit shader to select different callable shaders - std::vector accelerationStructureBuildRangeInfos{}; - for (uint32_t i = 0; i < objectCount; i++) { - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = numTriangles; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = i * sizeof(VkTransformMatrixKHR); - accelerationStructureBuildRangeInfos.push_back(accelerationStructureBuildRangeInfo); - } - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfos[0], &accelerationStructureBuildRangeInfos[1], &accelerationStructureBuildRangeInfos[2] }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - } - - /* - The top level acceleration structure contains the scene's object instances - */ - void createTopLevelAccelerationStructure() - { - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f }; - - VkAccelerationStructureInstanceKHR instance{}; - instance.transform = transformMatrix; - instance.instanceCustomIndex = 0; - instance.mask = 0xFF; - instance.instanceShaderBindingTableRecordOffset = 0; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = bottomLevelAS.deviceAddress; - - // Buffer for instance data - vks::Buffer instancesBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &instancesBuffer, - sizeof(VkAccelerationStructureInstanceKHR), - &instance)); - - VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{}; - instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer); - - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE; - accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - uint32_t primitive_count = 1; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &primitive_count, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(topLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the top level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = 1; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - instancesBuffer.destroy(); - } - - /* - Create the Shader Binding Tables that binds the programs and top-level acceleration structure - - SBT Layout used in this sample: - - /-----------\ - | raygen | - |-----------| - | miss | - |-----------| - | hit | - |-----------| - | callable0 | - | callable1 | - | callabel2 | - \-----------/ - - */ - void createShaderBindingTables() { - const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize; - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - const uint32_t groupCount = static_cast(shaderGroups.size()); - const uint32_t sbtSize = groupCount * handleSizeAligned; - - std::vector shaderHandleStorage(sbtSize); - VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data())); - - createShaderBindingTable(shaderBindingTables.raygen, 1); - createShaderBindingTable(shaderBindingTables.miss, 1); - createShaderBindingTable(shaderBindingTables.hit, 1); - // [POI] The callable shader binding table contains one shader handle per ray traced object - createShaderBindingTable(shaderBindingTables.callable, objectCount); - - // Copy handles - memcpy(shaderBindingTables.raygen.mapped, shaderHandleStorage.data(), handleSize); - memcpy(shaderBindingTables.miss.mapped, shaderHandleStorage.data() + handleSizeAligned, handleSize); - memcpy(shaderBindingTables.hit.mapped, shaderHandleStorage.data() + handleSizeAligned * 2, handleSize); - memcpy(shaderBindingTables.callable.mapped, shaderHandleStorage.data() + handleSizeAligned * 3, handleSize * 3); - } - - /* - Create the descriptor sets used for the ray tracing dispatch - */ - void createDescriptorSets() - { - std::vector poolSizes = { - { VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2 } - }; - VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool)); - - VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); - - VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks::initializers::writeDescriptorSetAccelerationStructureKHR(); - descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle; - - VkWriteDescriptorSet accelerationStructureWrite{}; - accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - // The specialized acceleration structure descriptor has to be chained - accelerationStructureWrite.pNext = &descriptorAccelerationStructureInfo; - accelerationStructureWrite.dstSet = descriptorSet; - accelerationStructureWrite.dstBinding = 0; - accelerationStructureWrite.descriptorCount = 1; - accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkDescriptorBufferInfo vertexBufferDescriptor{ vertexBuffer.buffer, 0, VK_WHOLE_SIZE }; - VkDescriptorBufferInfo indexBufferDescriptor{ indexBuffer.buffer, 0, VK_WHOLE_SIZE }; - - std::vector writeDescriptorSets = { - // Binding 0: Top level acceleration structure - accelerationStructureWrite, - // Binding 1: Ray tracing result image - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor), - // Binding 2: Uniform data - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor), - // Binding 3: Scene vertex buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &vertexBufferDescriptor), - // Binding 4: Scene index buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4, &indexBufferDescriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE); - } - - /* - Create our ray tracing pipeline - */ - void createRayTracingPipeline() - { - std::vector setLayoutBindings = { - // Binding 0: Acceleration structure - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0), - // Binding 1: Storage image - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_RAYGEN_BIT_KHR, 1), - // Binding 2: Uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR, 2), - // Binding 3: Vertex buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 3), - // Binding 4: Index buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 4), - }; - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pPipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCI, nullptr, &pipelineLayout)); - - /* - Setup ray tracing shader groups - */ - std::vector shaderStages; - VkRayTracingShaderGroupCreateInfoKHR shaderGroup; - - // Ray generation shader group - shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR)); - shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR(); - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - - // Miss shader group - shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR(); - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - - // Closest hit shader group - shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)); - shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR(); - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; - shaderGroup.generalShader = VK_SHADER_UNUSED_KHR; - shaderGroup.closestHitShader = static_cast(shaderStages.size()) - 1; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - - // [POI] Callable shader group - // This sample's hit shader will call different callable shaders depending on the geometry index using executeCallableEXT, so as we render three geometries, we'll also use three callable shaders - for (uint32_t i = 0; i < objectCount; i++) - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/callable" + std::to_string(i+1) + ".rcall.spv", VK_SHADER_STAGE_CALLABLE_BIT_KHR)); - shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR(); - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR(); - rayTracingPipelineCI.stageCount = static_cast(shaderStages.size()); - rayTracingPipelineCI.pStages = shaderStages.data(); - rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size()); - rayTracingPipelineCI.pGroups = shaderGroups.data(); - rayTracingPipelineCI.maxPipelineRayRecursionDepth = std::min(uint32_t(2), rayTracingPipelineProperties.maxRayRecursionDepth); - rayTracingPipelineCI.layout = pipelineLayout; - VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline)); - } - - /* - Create the uniform buffer used to pass matrices to the ray tracing ray generation shader - */ - void createUniformBuffer() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &ubo, - sizeof(uniformData), - &uniformData)); - VK_CHECK_RESULT(ubo.map()); - - updateUniformBuffers(); - } - - /* - If the window has been resized, we need to recreate the storage image and it's descriptor - */ - void handleResize() - { - // Recreate image - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - // Update descriptor - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - vkUpdateDescriptorSets(device, 1, &resultImageWrite, 0, VK_NULL_HANDLE); - resized = false; - } - - /* - Command buffer generation - */ - void buildCommandBuffers() - { - if (resized) - { - handleResize(); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Dispatch the ray tracing commands - */ - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0); - - vkCmdTraceRaysKHR( - drawCmdBuffers[i], - &shaderBindingTables.raygen.stridedDeviceAddressRegion, - &shaderBindingTables.miss.stridedDeviceAddressRegion, - &shaderBindingTables.hit.stridedDeviceAddressRegion, - &shaderBindingTables.callable.stridedDeviceAddressRegion, - width, - height, - 1); - - /* - Copy ray tracing output to swap chain image - */ - - // Prepare current swap chain image as transfer destination - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Prepare ray tracing output image as transfer source - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresourceRange); - - VkImageCopy copyRegion{}; - copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.srcOffset = { 0, 0, 0 }; - copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.dstOffset = { 0, 0, 0 }; - copyRegion.extent = { width, height, 1 }; - vkCmdCopyImage(drawCmdBuffers[i], storageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChain.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - // Transition swap chain image back for presentation - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresourceRange); - - // Transition ray tracing output image back to general layout - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresourceRange); - - drawUI(drawCmdBuffers[i], frameBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void updateUniformBuffers() - { - uniformData.projInverse = glm::inverse(camera.matrices.perspective); - uniformData.viewInverse = glm::inverse(camera.matrices.view); - memcpy(ubo.mapped, &uniformData, sizeof(uniformData)); - } - - void getEnabledFeatures() - { - // Enable features required for ray tracing using feature chaining via pNext - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR; - enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE; - enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures; - - enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE; - enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures; - - deviceCreatepNextChain = &enabledAccelerationStructureFeatures; - } - - void prepare() - { - VulkanRaytracingSample::prepare(); - - // Create the acceleration structures used to render the ray traced scene - createBottomLevelAccelerationStructure(); - createTopLevelAccelerationStructure(); - - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - createUniformBuffer(); - createRayTracingPipeline(); - createShaderBindingTables(); - createDescriptorSets(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (!paused || camera.updated) - updateUniformBuffers(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/raytracinggltf/raytracinggltf.cpp b/examples/raytracinggltf/raytracinggltf.cpp deleted file mode 100644 index 61255fd8..00000000 --- a/examples/raytracinggltf/raytracinggltf.cpp +++ /dev/null @@ -1,793 +0,0 @@ -/* - * Vulkan Example - Rendering a glTF model using hardware accelerated ray tracing example (for proper transparency, this sample does frame accumulation) - * - * Copyright (C) 2023-2025 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -#include "VulkanRaytracingSample.h" -#define VK_GLTF_MATERIAL_IDS -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanRaytracingSample -{ -public: - AccelerationStructure bottomLevelAS{}; - AccelerationStructure topLevelAS{}; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount{ 0 }; - vks::Buffer transformBuffer; - - struct GeometryNode { - uint64_t vertexBufferDeviceAddress; - uint64_t indexBufferDeviceAddress; - int32_t textureIndexBaseColor; - int32_t textureIndexOcclusion; - }; - vks::Buffer geometryNodesBuffer; - - std::vector shaderGroups{}; - struct ShaderBindingTables { - ShaderBindingTable raygen; - ShaderBindingTable miss; - ShaderBindingTable hit; - } shaderBindingTables; - - vks::Texture2D texture; - - struct UniformData { - glm::mat4 viewInverse; - glm::mat4 projInverse; - uint32_t frame{ 0 }; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - vkglTF::Model model; - - VkPhysicalDeviceDescriptorIndexingFeaturesEXT physicalDeviceDescriptorIndexingFeatures{}; - - VulkanExample() : VulkanRaytracingSample() - { - title = "Ray tracing glTF model"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, -0.1f, -1.0f)); - - enableExtensions(); - - // Buffer device address requires the 64-bit integer feature to be enabled - enabledFeatures.shaderInt64 = VK_TRUE; - - enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - deleteStorageImage(); - deleteAccelerationStructure(bottomLevelAS); - deleteAccelerationStructure(topLevelAS); - vertexBuffer.destroy(); - indexBuffer.destroy(); - transformBuffer.destroy(); - shaderBindingTables.raygen.destroy(); - shaderBindingTables.miss.destroy(); - shaderBindingTables.hit.destroy(); - uniformBuffer.destroy(); - geometryNodesBuffer.destroy(); - } - } - - void createAccelerationStructureBuffer(AccelerationStructure &accelerationStructure, VkAccelerationStructureBuildSizesInfoKHR buildSizeInfo) - { - VkBufferCreateInfo bufferCreateInfo{}; - bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferCreateInfo.size = buildSizeInfo.accelerationStructureSize; - bufferCreateInfo.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &accelerationStructure.buffer)); - VkMemoryRequirements memoryRequirements{}; - vkGetBufferMemoryRequirements(device, accelerationStructure.buffer, &memoryRequirements); - VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{}; - memoryAllocateFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; - memoryAllocateFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; - VkMemoryAllocateInfo memoryAllocateInfo{}; - memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memoryAllocateInfo.pNext = &memoryAllocateFlagsInfo; - memoryAllocateInfo.allocationSize = memoryRequirements.size; - memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &accelerationStructure.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, accelerationStructure.buffer, accelerationStructure.memory, 0)); - } - - /* - Create the bottom level acceleration structure that contains the scene's actual geometry (vertices, triangles) - */ - void createBottomLevelAccelerationStructure() - { - // Use transform matrices from the glTF nodes - std::vector transformMatrices{}; - for (auto node : model.linearNodes) { - if (node->mesh) { - for (auto primitive : node->mesh->primitives) { - if (primitive->indexCount > 0) { - VkTransformMatrixKHR transformMatrix{}; - auto m = glm::mat3x4(glm::transpose(node->getMatrix())); - memcpy(&transformMatrix, (void*)&m, sizeof(glm::mat3x4)); - transformMatrices.push_back(transformMatrix); - } - } - } - } - - // Transform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &transformBuffer, - static_cast(transformMatrices.size()) * sizeof(VkTransformMatrixKHR), - transformMatrices.data())); - - // Build - // One geometry per glTF node, so we can index materials using gl_GeometryIndexEXT - std::vector maxPrimitiveCounts{}; - std::vector geometries{}; - std::vector buildRangeInfos{}; - std::vector pBuildRangeInfos{}; - std::vector geometryNodes{}; - for (auto node : model.linearNodes) { - if (node->mesh) { - for (auto primitive : node->mesh->primitives) { - if (primitive->indexCount > 0) { - VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR transformBufferDeviceAddress{}; - - vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(model.vertices.buffer);// +primitive->firstVertex * sizeof(vkglTF::Vertex); - indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(model.indices.buffer) + primitive->firstIndex * sizeof(uint32_t); - transformBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(transformBuffer.buffer) + static_cast(geometryNodes.size()) * sizeof(VkTransformMatrixKHR); - - VkAccelerationStructureGeometryKHR geometry{}; - geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; - geometry.geometry.triangles.vertexData = vertexBufferDeviceAddress; - geometry.geometry.triangles.maxVertex = model.vertices.count; - //geometry.geometry.triangles.maxVertex = primitive->vertexCount; - geometry.geometry.triangles.vertexStride = sizeof(vkglTF::Vertex); - geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; - geometry.geometry.triangles.indexData = indexBufferDeviceAddress; - geometry.geometry.triangles.transformData = transformBufferDeviceAddress; - geometries.push_back(geometry); - maxPrimitiveCounts.push_back(primitive->indexCount / 3); - - VkAccelerationStructureBuildRangeInfoKHR buildRangeInfo{}; - buildRangeInfo.firstVertex = 0; - buildRangeInfo.primitiveOffset = 0; // primitive->firstIndex * sizeof(uint32_t); - buildRangeInfo.primitiveCount = primitive->indexCount / 3; - buildRangeInfo.transformOffset = 0; - buildRangeInfos.push_back(buildRangeInfo); - - GeometryNode geometryNode{}; - geometryNode.vertexBufferDeviceAddress = vertexBufferDeviceAddress.deviceAddress; - geometryNode.indexBufferDeviceAddress = indexBufferDeviceAddress.deviceAddress; - geometryNode.textureIndexBaseColor = primitive->material.baseColorTexture->index; - geometryNode.textureIndexOcclusion = primitive->material.occlusionTexture ? primitive->material.occlusionTexture->index : -1; - geometryNodes.push_back(geometryNode); - } - } - } - } - for (auto& rangeInfo : buildRangeInfos) { - pBuildRangeInfos.push_back(&rangeInfo); - } - - vks::Buffer stagingBuffer; - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - static_cast(geometryNodes.size()) * sizeof(GeometryNode), - geometryNodes.data())); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &geometryNodesBuffer, - static_cast(geometryNodes.size()) * sizeof(GeometryNode))); - - vulkanDevice->copyBuffer(&stagingBuffer, &geometryNodesBuffer, queue); - - stagingBuffer.destroy(); - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{}; - accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = static_cast(geometries.size()); - accelerationStructureBuildGeometryInfo.pGeometries = geometries.data(); - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{}; - accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - maxPrimitiveCounts.data(), - &accelerationStructureBuildSizesInfo); - - createAccelerationStructureBuffer(bottomLevelAS, accelerationStructureBuildSizesInfo); - - VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{}; - accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - accelerationStructureCreateInfo.buffer = bottomLevelAS.buffer; - accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize; - accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &bottomLevelAS.handle); - - // Create a small scratch buffer used during build of the bottom level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - accelerationStructureBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationStructureBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle; - accelerationStructureBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - const VkAccelerationStructureBuildRangeInfoKHR* buildOffsetInfo = buildRangeInfos.data(); - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationStructureBuildGeometryInfo, - pBuildRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{}; - accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; - accelerationDeviceAddressInfo.accelerationStructure = bottomLevelAS.handle; - bottomLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo); - - deleteScratchBuffer(scratchBuffer); - } - - /* - The top level acceleration structure contains the scene's object instances - */ - void createTopLevelAccelerationStructure() - { - // We flip the matrix [1][1] = -1.0f to accomodate for the glTF up vector - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, -1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f }; - - VkAccelerationStructureInstanceKHR instance{}; - instance.transform = transformMatrix; - instance.instanceCustomIndex = 0; - instance.mask = 0xFF; - instance.instanceShaderBindingTableRecordOffset = 0; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = bottomLevelAS.deviceAddress; - - // Buffer for instance data - vks::Buffer instancesBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &instancesBuffer, - sizeof(VkAccelerationStructureInstanceKHR), - &instance)); - - VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{}; - instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer); - - VkAccelerationStructureGeometryKHR accelerationStructureGeometry{}; - accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE; - accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress; - - // Get size info - /* - The pSrcAccelerationStructure, dstAccelerationStructure, and mode members of pBuildInfo are ignored. Any VkDeviceOrHostAddressKHR members of pBuildInfo are ignored by this command, except that the hostAddress member of VkAccelerationStructureGeometryTrianglesDataKHR::transformData will be examined to check if it is NULL.* - */ - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{}; - accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - uint32_t primitive_count = 1; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{}; - accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &primitive_count, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructureBuffer(topLevelAS, accelerationStructureBuildSizesInfo); - - VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{}; - accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - accelerationStructureCreateInfo.buffer = topLevelAS.buffer; - accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize; - accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &topLevelAS.handle); - - // Create a small scratch buffer used during build of the top level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{}; - accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = 1; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{}; - accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; - accelerationDeviceAddressInfo.accelerationStructure = topLevelAS.handle; - - deleteScratchBuffer(scratchBuffer); - instancesBuffer.destroy(); - } - - /* - Create the Shader Binding Tables that binds the programs and top-level acceleration structure - - SBT Layout used in this sample: - - /-----------\ - | raygen | - |-----------| - | miss + shadow | - |-----------| - | hit + any | - \-----------/ - - */ - void createShaderBindingTables() { - const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize; - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - const uint32_t groupCount = static_cast(shaderGroups.size()); - const uint32_t sbtSize = groupCount * handleSizeAligned; - - std::vector shaderHandleStorage(sbtSize); - VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data())); - - createShaderBindingTable(shaderBindingTables.raygen, 1); - createShaderBindingTable(shaderBindingTables.miss, 2); - createShaderBindingTable(shaderBindingTables.hit, 1); - - // Copy handles - memcpy(shaderBindingTables.raygen.mapped, shaderHandleStorage.data(), handleSize); - // We are using two miss shaders, so we need to get two handles for the miss shader binding table - memcpy(shaderBindingTables.miss.mapped, shaderHandleStorage.data() + handleSizeAligned, handleSize * 2); - memcpy(shaderBindingTables.hit.mapped, shaderHandleStorage.data() + handleSizeAligned * 3, handleSize); - } - - /* - Create our ray tracing pipeline - */ - void createRayTracingPipeline() - { - const uint32_t imageCount = static_cast(model.textures.size()); - - std::vector setLayoutBindings = { - // Binding 0: Top level acceleration structure - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0), - // Binding 1: Ray tracing result image - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_RAYGEN_BIT_KHR, 1), - // Binding 2: Uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR, 2), - // Binding 3: Texture image - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR, 3), - // Binding 4: Geometry node information SSBO - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR, 4), - // Binding 5: All images used by the glTF model - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR, 5, imageCount) - }; - - // Unbound set - VkDescriptorSetLayoutBindingFlagsCreateInfoEXT setLayoutBindingFlags{}; - setLayoutBindingFlags.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT; - setLayoutBindingFlags.bindingCount = 6; - std::vector descriptorBindingFlags = { - 0, - 0, - 0, - 0, - 0, - VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT - }; - setLayoutBindingFlags.pBindingFlags = descriptorBindingFlags.data(); - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - descriptorSetLayoutCI.pNext = &setLayoutBindingFlags; - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - /* - Setup ray tracing shader groups - */ - std::vector shaderStages; - - // Ray generation group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracinggltf/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Miss group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracinggltf/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - // Second shader for shadows - shaderStages.push_back(loadShader(getShadersPath() + "raytracinggltf/shadow.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroups.push_back(shaderGroup); - } - - // Closest hit group for doing texture lookups - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracinggltf/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; - shaderGroup.generalShader = VK_SHADER_UNUSED_KHR; - shaderGroup.closestHitShader = static_cast(shaderStages.size()) - 1; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - // This group also uses an anyhit shader for doing transparency (see anyhit.rahit for details) - shaderStages.push_back(loadShader(getShadersPath() + "raytracinggltf/anyhit.rahit.spv", VK_SHADER_STAGE_ANY_HIT_BIT_KHR)); - shaderGroup.anyHitShader = static_cast(shaderStages.size()) - 1; - shaderGroups.push_back(shaderGroup); - } - - /* - Create the ray tracing pipeline - */ - VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI{}; - rayTracingPipelineCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; - rayTracingPipelineCI.stageCount = static_cast(shaderStages.size()); - rayTracingPipelineCI.pStages = shaderStages.data(); - rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size()); - rayTracingPipelineCI.pGroups = shaderGroups.data(); - rayTracingPipelineCI.maxPipelineRayRecursionDepth = 1; - rayTracingPipelineCI.layout = pipelineLayout; - VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline)); - } - - /* - Create the descriptor sets used for the ray tracing dispatch - */ - void createDescriptorSets() - { - uint32_t imageCount = static_cast(model.textures.size()); - std::vector poolSizes = { - { VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 }, - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1 }, - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(model.textures.size()) } - }; - VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool)); - - VkDescriptorSetVariableDescriptorCountAllocateInfoEXT variableDescriptorCountAllocInfo{}; - uint32_t variableDescCounts[] = { imageCount }; - variableDescriptorCountAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT; - variableDescriptorCountAllocInfo.descriptorSetCount = 1; - variableDescriptorCountAllocInfo.pDescriptorCounts = variableDescCounts; - - VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - descriptorSetAllocateInfo.pNext = &variableDescriptorCountAllocInfo; - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); - - VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks::initializers::writeDescriptorSetAccelerationStructureKHR(); - descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle; - - VkWriteDescriptorSet accelerationStructureWrite{}; - accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - // The specialized acceleration structure descriptor has to be chained - accelerationStructureWrite.pNext = &descriptorAccelerationStructureInfo; - accelerationStructureWrite.dstSet = descriptorSet; - accelerationStructureWrite.dstBinding = 0; - accelerationStructureWrite.descriptorCount = 1; - accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - - std::vector writeDescriptorSets = { - // Binding 0: Top level acceleration structure - accelerationStructureWrite, - // Binding 1: Ray tracing result image - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor), - // Binding 2: Uniform data - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &uniformBuffer.descriptor), - // Binding 4: Geometry node information SSBO - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4, &geometryNodesBuffer.descriptor), - }; - - // Image descriptors for the image array - std::vector textureDescriptors{}; - for (auto texture : model.textures) { - VkDescriptorImageInfo descriptor{}; - descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - descriptor.sampler = texture.sampler;; - descriptor.imageView = texture.view; - textureDescriptors.push_back(descriptor); - } - - VkWriteDescriptorSet writeDescriptorImgArray{}; - writeDescriptorImgArray.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorImgArray.dstBinding = 5; - writeDescriptorImgArray.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorImgArray.descriptorCount = imageCount; - writeDescriptorImgArray.dstSet = descriptorSet; - writeDescriptorImgArray.pImageInfo = textureDescriptors.data(); - writeDescriptorSets.push_back(writeDescriptorImgArray); - - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE); - } - - /* - Create the uniform buffer used to pass matrices to the ray tracing ray generation shader - */ - void createUniformBuffer() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffer, - sizeof(uniformData), - &uniformData)); - VK_CHECK_RESULT(uniformBuffer.map()); - - updateUniformBuffers(); - } - - /* - If the window has been resized, we need to recreate the storage image and it's descriptor - */ - void handleResize() - { - // Recreate image - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - // Update descriptor - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - vkUpdateDescriptorSets(device, 1, &resultImageWrite, 0, VK_NULL_HANDLE); - resized = false; - } - - /* - Command buffer generation - */ - void buildCommandBuffers() - { - if (resized) - { - handleResize(); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Dispatch the ray tracing commands - */ - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0); - - VkStridedDeviceAddressRegionKHR emptySbtEntry = {}; - vkCmdTraceRaysKHR( - drawCmdBuffers[i], - &shaderBindingTables.raygen.stridedDeviceAddressRegion, - &shaderBindingTables.miss.stridedDeviceAddressRegion, - &shaderBindingTables.hit.stridedDeviceAddressRegion, - &emptySbtEntry, - width, - height, - 1); - - /* - Copy ray tracing output to swap chain image - */ - - // Prepare current swap chain image as transfer destination - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Prepare ray tracing output image as transfer source - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresourceRange); - - VkImageCopy copyRegion{}; - copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.srcOffset = { 0, 0, 0 }; - copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.dstOffset = { 0, 0, 0 }; - copyRegion.extent = { width, height, 1 }; - vkCmdCopyImage(drawCmdBuffers[i], storageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChain.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - // Transition swap chain image back for presentation - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresourceRange); - - // Transition ray tracing output image back to general layout - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresourceRange); - - drawUI(drawCmdBuffers[i], frameBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void updateUniformBuffers() - { - uniformData.projInverse = glm::inverse(camera.matrices.perspective); - uniformData.viewInverse = glm::inverse(camera.matrices.view); - // This value is used to accumulate multiple frames into the finale picture - // It's required as ray tracing needs to do multiple passes for transparency - // In this sample we use noise offset by this frame index to shoot rays for transparency into different directions - // Once enough frames with random ray directions have been accumulated, it looks like proper transparency - uniformData.frame++; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void getEnabledFeatures() - { - // Enable features required for ray tracing using feature chaining via pNext - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR; - enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE; - enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures; - - enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE; - enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures; - - physicalDeviceDescriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; - physicalDeviceDescriptorIndexingFeatures.shaderSampledImageArrayNonUniformIndexing = VK_TRUE; - physicalDeviceDescriptorIndexingFeatures.runtimeDescriptorArray = VK_TRUE; - physicalDeviceDescriptorIndexingFeatures.descriptorBindingVariableDescriptorCount = VK_TRUE; - physicalDeviceDescriptorIndexingFeatures.pNext = &enabledAccelerationStructureFeatures; - - deviceCreatepNextChain = &physicalDeviceDescriptorIndexingFeatures; - - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - - void loadAssets() - { - vkglTF::memoryPropertyFlags = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - model.loadFromFile(getAssetPath() + "models/FlightHelmet/glTF/FlightHelmet.gltf", vulkanDevice, queue); - } - - void prepare() - { - VulkanRaytracingSample::prepare(); - - loadAssets(); - - // Create the acceleration structures used to render the ray traced scene - createBottomLevelAccelerationStructure(); - createTopLevelAccelerationStructure(); - - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - createUniformBuffer(); - createRayTracingPipeline(); - createShaderBindingTables(); - createDescriptorSets(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - if (camera.updated) { - // If the camera's view has been updated we reset the frame accumulation - uniformData.frame = -1; - } - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/raytracingintersection/raytracingintersection.cpp b/examples/raytracingintersection/raytracingintersection.cpp deleted file mode 100644 index b716eba6..00000000 --- a/examples/raytracingintersection/raytracingintersection.cpp +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Vulkan Example - Hardware accelerated ray tracing intersection shader samples - * - * Copyright (C) 2023-2024 by Sascha Willems - www.saschawillems.de - * - * This sample uses intersection shaders for doing prodcedural ray traced geometry - * Instead of passing actual geometry, this samples only passes bounding boxes and sphere descriptions - * The bounding boxes are used for the ray traversal and the sphere intersections are done - * within the intersection shader - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -#include "VulkanRaytracingSample.h" - -class VulkanExample : public VulkanRaytracingSample -{ -public: - AccelerationStructure bottomLevelAS; - AccelerationStructure topLevelAS; - - std::vector shaderGroups{}; - struct ShaderBindingTables { - ShaderBindingTable raygen; - ShaderBindingTable miss; - ShaderBindingTable hit; - } shaderBindingTables; - - struct UniformData { - glm::mat4 viewInverse; - glm::mat4 projInverse; - glm::vec4 lightPos; - } uniformData; - vks::Buffer ubo; - - VkPipeline pipeline; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; - - struct Sphere { - glm::vec3 center; - float radius; - glm::vec4 color; - }; - - struct AABB { - glm::vec3 min; - glm::vec3 max; - }; - - vks::Buffer spheresBuffer; - vks::Buffer aabbsBuffer; - uint32_t aabbCount{ 0 }; - - // This sample is derived from an extended base class that saves most of the ray tracing setup boiler plate - VulkanExample() : VulkanRaytracingSample() - { - title = "Ray tracing intersection shaders"; - timerSpeed *= 0.25f; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -60.0f)); - enableExtensions(); - } - - ~VulkanExample() - { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - deleteStorageImage(); - deleteAccelerationStructure(bottomLevelAS); - deleteAccelerationStructure(topLevelAS); - shaderBindingTables.raygen.destroy(); - shaderBindingTables.miss.destroy(); - shaderBindingTables.hit.destroy(); - ubo.destroy(); - spheresBuffer.destroy(); - aabbsBuffer.destroy(); - } - - void createBuffers() - { - // We'll be using two buffers to describe the procedural geometry - - // A buffer with randpmly generatd sphere descriptions (center, radius, material) that'll be passed to the ray tracing shaders as a shader storage buffer object - std::vector spheres{}; - std::default_random_engine rndGenerator(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::uniform_real_distribution uniformDist(0.0, 1.0); - std::uniform_real_distribution sizeDist(1.0, 2.0); - for (uint32_t i = 0; i < 1024; i++) { - Sphere sphere{}; - //sphere.center = - sphere.radius = sizeDist(rndGenerator); - sphere.color = glm::vec4(uniformDist(rndGenerator), uniformDist(rndGenerator), uniformDist(rndGenerator), 1.0f); - // Get a random point in a sphere - float x,y,z,d{ 0.0f }; - do { - x = uniformDist(rndGenerator) * 2.0f - 1.0f; - y = uniformDist(rndGenerator) * 2.0f - 1.0f; - z = uniformDist(rndGenerator) * 2.0f - 1.0f; - d = x * x + y * y + z * z; - - } while (d > 1.0); - sphere.center = glm::vec3(x, y, z) * 25.0f; - spheres.push_back(sphere); - } - - // A buffer with the (axis aligned) bounding boxes of our sphere, which is used during the ray tracing traversal for hit detection - std::vector aabbs{}; - for (auto& sphere : spheres) { - aabbs.push_back({ sphere.center - glm::vec3(sphere.radius), sphere.center + glm::vec3(sphere.radius) }); - } - aabbCount = static_cast(aabbs.size()); - - // Copy the buffer to the device for performance reasons - vks::Buffer stagingBuffer{}; - VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - - // Spheres - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer, sizeof(Sphere)* spheres.size(), spheres.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer(usageFlags, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &spheresBuffer, sizeof(Sphere)* spheres.size())); - vulkanDevice->copyBuffer(&stagingBuffer, &spheresBuffer, queue); - stagingBuffer.destroy(); - - // AABBs - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer, sizeof(AABB)* aabbs.size(), aabbs.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer(usageFlags, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &aabbsBuffer, sizeof(AABB)* aabbs.size())); - vulkanDevice->copyBuffer(&stagingBuffer, &aabbsBuffer, queue); - stagingBuffer.destroy(); - } - - /* - Create the bottom level acceleration structure only containing axis aligned bounding boxes for our procedural geometry - */ - void createBottomLevelAccelerationStructure() - { - // Build - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - // Instead of providing actual geometry (e.g. triangles), we only provide the axis aligned bounding boxes (AABBs) of the spheres - // The data for the actual spheres is passed elsewhere as a shader storage buffer object - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; - accelerationStructureGeometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR; - accelerationStructureGeometry.geometry.aabbs.data.deviceAddress = getBufferDeviceAddress(aabbsBuffer.buffer); - accelerationStructureGeometry.geometry.aabbs.stride = sizeof(AABB); - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &aabbCount, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(bottomLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the bottom level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = aabbCount; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - } - - /* - The top level acceleration structure contains the scene's object instances - */ - void createTopLevelAccelerationStructure() - { - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f }; - - VkAccelerationStructureInstanceKHR instance{}; - instance.transform = transformMatrix; - instance.instanceCustomIndex = 0; - instance.mask = 0xFF; - instance.instanceShaderBindingTableRecordOffset = 0; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = bottomLevelAS.deviceAddress; - - // Buffer for instance data - vks::Buffer instancesBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &instancesBuffer, - sizeof(VkAccelerationStructureInstanceKHR), - &instance)); - - VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{}; - instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer); - - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE; - accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - uint32_t primitive_count = 1; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &primitive_count, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(topLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the top level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = 1; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - instancesBuffer.destroy(); - } - - - /* - Create the Shader Binding Tables that binds the programs and top-level acceleration structure - - SBT Layout used in this sample: - - /-----------\ - | raygen | - |-----------| - | miss | - |-----------| - | hit + int | - \-----------/ - - */ - void createShaderBindingTables() { - const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize; - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - const uint32_t groupCount = static_cast(shaderGroups.size()); - const uint32_t sbtSize = groupCount * handleSizeAligned; - - std::vector shaderHandleStorage(sbtSize); - VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data())); - - createShaderBindingTable(shaderBindingTables.raygen, 1); - createShaderBindingTable(shaderBindingTables.miss, 1); - createShaderBindingTable(shaderBindingTables.hit, 1); - - // Copy handles - memcpy(shaderBindingTables.raygen.mapped, shaderHandleStorage.data(), handleSize); - memcpy(shaderBindingTables.miss.mapped, shaderHandleStorage.data() + handleSizeAligned, handleSize); - memcpy(shaderBindingTables.hit.mapped, shaderHandleStorage.data() + handleSizeAligned * 2, handleSize); - } - - /* - Create the descriptor sets used for the ray tracing dispatch - */ - void createDescriptorSets() - { - std::vector poolSizes = { - { VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2 } - }; - VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool)); - - VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); - - VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks::initializers::writeDescriptorSetAccelerationStructureKHR(); - descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle; - - VkWriteDescriptorSet accelerationStructureWrite{}; - accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - // The specialized acceleration structure descriptor has to be chained - accelerationStructureWrite.pNext = &descriptorAccelerationStructureInfo; - accelerationStructureWrite.dstSet = descriptorSet; - accelerationStructureWrite.dstBinding = 0; - accelerationStructureWrite.descriptorCount = 1; - accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - - // We pass the sphere descriptions as shader storage buffer, so the ray tracing shaders can source properties from it - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkDescriptorBufferInfo spheresBufferDescriptor{ spheresBuffer.buffer, 0, VK_WHOLE_SIZE }; - - std::vector writeDescriptorSets = { - // Binding 0: Top level acceleration structure - accelerationStructureWrite, - // Binding 1: Ray tracing result image - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor), - // Binding 2: Uniform data - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor), - // Binding 3: Spheres buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &spheresBufferDescriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE); - } - - /* - Create our ray tracing pipeline - */ - void createRayTracingPipeline() - { - std::vector setLayoutBindings = { - // Binding 0: Acceleration structure - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0), - // Binding 1: Storage image - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_RAYGEN_BIT_KHR, 1), - // Binding 2: Uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR, 2), - // Binding 3: Spheres buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR, 3), - }; - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pPipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCI, nullptr, &pipelineLayout)); - - /* - Setup ray tracing shader groups - */ - std::vector shaderStages; - - // Ray generation group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingintersection/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Miss group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingintersection/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Closest hit group (procedural) - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingintersection/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; - shaderGroup.generalShader = VK_SHADER_UNUSED_KHR; - shaderGroup.closestHitShader = static_cast(shaderStages.size()) - 1; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - // This group als uses an intersection shader for proedural geometry (see interseciton.rint for details) - shaderStages.push_back(loadShader(getShadersPath() + "raytracingintersection/intersection.rint.spv", VK_SHADER_STAGE_INTERSECTION_BIT_KHR)); - shaderGroup.intersectionShader = static_cast(shaderStages.size()) - 1; - shaderGroups.push_back(shaderGroup); - } - - VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR(); - rayTracingPipelineCI.stageCount = static_cast(shaderStages.size()); - rayTracingPipelineCI.pStages = shaderStages.data(); - rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size()); - rayTracingPipelineCI.pGroups = shaderGroups.data(); - rayTracingPipelineCI.maxPipelineRayRecursionDepth = std::min(uint32_t(2), rayTracingPipelineProperties.maxRayRecursionDepth); - rayTracingPipelineCI.layout = pipelineLayout; - VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline)); - } - - /* - Create the uniform buffer used to pass matrices to the ray tracing ray generation shader - */ - void createUniformBuffer() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &ubo, - sizeof(uniformData), - &uniformData)); - VK_CHECK_RESULT(ubo.map()); - - updateUniformBuffers(); - } - - /* - If the window has been resized, we need to recreate the storage image and it's descriptor - */ - void handleResize() - { - // Recreate image - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - // Update descriptor - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - vkUpdateDescriptorSets(device, 1, &resultImageWrite, 0, VK_NULL_HANDLE); - resized = false; - } - - /* - Command buffer generation - */ - void buildCommandBuffers() - { - if (resized) - { - handleResize(); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Dispatch the ray tracing commands - */ - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0); - - VkStridedDeviceAddressRegionKHR emptySbtEntry = {}; - vkCmdTraceRaysKHR( - drawCmdBuffers[i], - &shaderBindingTables.raygen.stridedDeviceAddressRegion, - &shaderBindingTables.miss.stridedDeviceAddressRegion, - &shaderBindingTables.hit.stridedDeviceAddressRegion, - &emptySbtEntry, - width, - height, - 1); - - /* - Copy ray tracing output to swap chain image - */ - - // Prepare current swap chain image as transfer destination - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Prepare ray tracing output image as transfer source - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresourceRange); - - VkImageCopy copyRegion{}; - copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.srcOffset = { 0, 0, 0 }; - copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.dstOffset = { 0, 0, 0 }; - copyRegion.extent = { width, height, 1 }; - vkCmdCopyImage(drawCmdBuffers[i], storageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChain.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - // Transition swap chain image back for presentation - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresourceRange); - - // Transition ray tracing output image back to general layout - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresourceRange); - - drawUI(drawCmdBuffers[i], frameBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void updateUniformBuffers() - { - uniformData.projInverse = glm::inverse(camera.matrices.perspective); - uniformData.viewInverse = glm::inverse(camera.matrices.view); - uniformData.lightPos = glm::vec4(cos(glm::radians(timer * 360.0f)) * 60.0f, 0.0f, 25.0f + sin(glm::radians(timer * 360.0f)) * 60.0f, 0.0f); - memcpy(ubo.mapped, &uniformData, sizeof(uniformData)); - } - - void getEnabledFeatures() - { - // Enable features required for ray tracing using feature chaining via pNext - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR; - enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE; - enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures; - - enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE; - enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures; - - deviceCreatepNextChain = &enabledAccelerationStructureFeatures; - } - - void prepare() - { - VulkanRaytracingSample::prepare(); - - createBuffers(); - - // Create the acceleration structures used to render the ray traced scene - createBottomLevelAccelerationStructure(); - createTopLevelAccelerationStructure(); - - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - createUniformBuffer(); - createRayTracingPipeline(); - createShaderBindingTables(); - createDescriptorSets(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (!paused || camera.updated) - updateUniformBuffers(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/raytracingpositionfetch/raytracingpositionfetch.cpp b/examples/raytracingpositionfetch/raytracingpositionfetch.cpp deleted file mode 100644 index 21d6012f..00000000 --- a/examples/raytracingpositionfetch/raytracingpositionfetch.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/* -* Vulkan Example - Using position fetch with hardware accelerated ray tracing -* -* Shows how to use the VK_KHR_ray_tracing_position_fetch extension to fetch the vertex positions in the shader from a hit triangle as stored in the acceleration structure -* See https://www.khronos.org/blog/introducing-vulkan-ray-tracing-position-fetch-extension -* -* Copyright (C) 2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "VulkanRaytracingSample.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanRaytracingSample -{ -public: - AccelerationStructure bottomLevelAS{}; - AccelerationStructure topLevelAS{}; - - std::vector shaderGroups{}; - struct ShaderBindingTables { - ShaderBindingTable raygen; - ShaderBindingTable miss; - ShaderBindingTable hit; - } shaderBindingTables; - - struct UniformData { - glm::mat4 viewInverse; - glm::mat4 projInverse; - glm::vec4 lightPos; - } uniformData; - vks::Buffer ubo; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - vkglTF::Model scene; - - // This extension comes with a dedicated feature structure - VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR enabledRayTracingPositionFetchFeatures{}; - - // This sample is derived from an extended base class that saves most of the ray tracing setup boiler plate - VulkanExample() : VulkanRaytracingSample() - { - title = "Ray tracing position fetch"; - timerSpeed *= 0.5f; - camera.rotationSpeed *= 0.25f; - camera.type = Camera::CameraType::firstperson; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 3.0f, -10.0f)); - enableExtensions(); - // Enable new extension - enabledDeviceExtensions.push_back(VK_KHR_RAY_TRACING_POSITION_FETCH_EXTENSION_NAME); - // The corresponding GLSL extension is GL_EXT_ray_tracing_position_fetch - } - - ~VulkanExample() - { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - deleteStorageImage(); - deleteAccelerationStructure(bottomLevelAS); - deleteAccelerationStructure(topLevelAS); - shaderBindingTables.raygen.destroy(); - shaderBindingTables.miss.destroy(); - shaderBindingTables.hit.destroy(); - ubo.destroy(); - } - - /* - Create the bottom level acceleration structure containing the scene's actual geometry (vertices, triangles) - */ - void createBottomLevelAccelerationStructure() - { - // Instead of a simple triangle, we'll be loading a more complex scene for this example - // The shaders are accessing the vertex and index buffers of the scene, so the proper usage flag has to be set on the vertex and index buffers for the scene - vkglTF::memoryPropertyFlags = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - scene.loadFromFile(getAssetPath() + "models/treasure_smooth.gltf", vulkanDevice, queue, glTFLoadingFlags); - - VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{}; - - vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.vertices.buffer); - indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.indices.buffer); - - uint32_t numTriangles = static_cast(scene.indices.count) / 3; - - // Build - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; - accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.maxVertex = scene.vertices.count - 1; - accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(vkglTF::Vertex); - accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; - accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0; - accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - // We will access vertex positions from the bottom AS in the shader, so we need to set the VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR | VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR(device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &accelerationStructureBuildGeometryInfo, &numTriangles, &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(bottomLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the bottom level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - // We will access vertex positions from the bottom AS in the shader, so we need to set the VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR | VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = numTriangles; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR(commandBuffer, 1, &accelerationBuildGeometryInfo, accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - } - - /* - The top level acceleration structure contains the scene's object instances - */ - void createTopLevelAccelerationStructure() - { - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f }; - - VkAccelerationStructureInstanceKHR instance{}; - instance.transform = transformMatrix; - instance.instanceCustomIndex = 0; - instance.mask = 0xFF; - instance.instanceShaderBindingTableRecordOffset = 0; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = bottomLevelAS.deviceAddress; - - // Buffer for instance data - vks::Buffer instancesBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &instancesBuffer, - sizeof(VkAccelerationStructureInstanceKHR), - &instance)); - - VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{}; - instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer); - - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE; - accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - uint32_t primitive_count = 1; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR(device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &accelerationStructureBuildGeometryInfo, &primitive_count, &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(topLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the top level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = 1; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR(commandBuffer, 1, &accelerationBuildGeometryInfo, accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - instancesBuffer.destroy(); - } - - /* - Create the Shader Binding Tables that binds the programs and top-level acceleration structure - - SBT Layout used in this sample: - - /-----------\ - | raygen | - |-----------| - | miss | - |-----------| - | hit | - \-----------/ - - */ - void createShaderBindingTables() { - const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize; - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - const uint32_t groupCount = static_cast(shaderGroups.size()); - const uint32_t sbtSize = groupCount * handleSizeAligned; - - std::vector shaderHandleStorage(sbtSize); - VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data())); - - createShaderBindingTable(shaderBindingTables.raygen, 1); - createShaderBindingTable(shaderBindingTables.miss, 1); - createShaderBindingTable(shaderBindingTables.hit, 1); - - // Copy handles - memcpy(shaderBindingTables.raygen.mapped, shaderHandleStorage.data(), handleSize); - memcpy(shaderBindingTables.miss.mapped, shaderHandleStorage.data() + handleSizeAligned, handleSize); - memcpy(shaderBindingTables.hit.mapped, shaderHandleStorage.data() + handleSizeAligned * 2, handleSize); - } - - /* - Create the descriptor sets used for the ray tracing dispatch - */ - void createDescriptors() - { - // Pools - std::vector poolSizes = { - { VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 } - }; - VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool)); - - VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); - - // Descriptors - VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks::initializers::writeDescriptorSetAccelerationStructureKHR(); - descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle; - - VkWriteDescriptorSet accelerationStructureWrite{}; - accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - // The specialized acceleration structure descriptor has to be chained - accelerationStructureWrite.pNext = &descriptorAccelerationStructureInfo; - accelerationStructureWrite.dstSet = descriptorSet; - accelerationStructureWrite.dstBinding = 0; - accelerationStructureWrite.descriptorCount = 1; - accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkDescriptorBufferInfo vertexBufferDescriptor{ scene.vertices.buffer, 0, VK_WHOLE_SIZE }; - VkDescriptorBufferInfo indexBufferDescriptor{ scene.indices.buffer, 0, VK_WHOLE_SIZE }; - - std::vector writeDescriptorSets = { - // Binding 0: Top level acceleration structure - accelerationStructureWrite, - // Binding 1: Ray tracing result image - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor), - // Binding 2: Uniform data - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE); - } - - /* - Create our ray tracing pipeline - */ - void createRayTracingPipeline() - { - std::vector setLayoutBindings = { - // Binding 0: Acceleration structure - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0), - // Binding 1: Storage image - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_RAYGEN_BIT_KHR, 1), - // Binding 2: Uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR, 2), - }; - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pPipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCI, nullptr, &pipelineLayout)); - - /* - Setup ray tracing shader groups - */ - std::vector shaderStages; - - // Ray generation group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingpositionfetch/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Miss group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingpositionfetch/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Closest hit group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingpositionfetch/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; - shaderGroup.generalShader = VK_SHADER_UNUSED_KHR; - shaderGroup.closestHitShader = static_cast(shaderStages.size()) - 1; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR(); - rayTracingPipelineCI.stageCount = static_cast(shaderStages.size()); - rayTracingPipelineCI.pStages = shaderStages.data(); - rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size()); - rayTracingPipelineCI.pGroups = shaderGroups.data(); - rayTracingPipelineCI.maxPipelineRayRecursionDepth = 1; - rayTracingPipelineCI.layout = pipelineLayout; - VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline)); - } - - /* - Create the uniform buffer used to pass matrices to the ray tracing ray generation shader - */ - void createUniformBuffer() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &ubo, sizeof(uniformData), &uniformData)); - VK_CHECK_RESULT(ubo.map()); - updateUniformBuffers(); - } - - /* - If the window has been resized, we need to recreate the storage image and it's descriptor - */ - void handleResize() - { - // Recreate image - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - // Update descriptor - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - vkUpdateDescriptorSets(device, 1, &resultImageWrite, 0, VK_NULL_HANDLE); - resized = false; - } - - /* - Command buffer generation - */ - void buildCommandBuffers() - { - if (resized) - { - handleResize(); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0); - - /* - Dispatch the ray tracing commands - */ - VkStridedDeviceAddressRegionKHR emptySbtEntry = {}; - vkCmdTraceRaysKHR( - drawCmdBuffers[i], - &shaderBindingTables.raygen.stridedDeviceAddressRegion, - &shaderBindingTables.miss.stridedDeviceAddressRegion, - &shaderBindingTables.hit.stridedDeviceAddressRegion, - &emptySbtEntry, - width, - height, - 1); - - /* - Copy ray tracing output to swap chain image - */ - - // Prepare current swap chain image as transfer destination - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Prepare ray tracing output image as transfer source - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresourceRange); - - VkImageCopy copyRegion{}; - copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.srcOffset = { 0, 0, 0 }; - copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.dstOffset = { 0, 0, 0 }; - copyRegion.extent = { width, height, 1 }; - vkCmdCopyImage(drawCmdBuffers[i], storageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChain.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - // Transition swap chain image back for presentation - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresourceRange); - - // Transition ray tracing output image back to general layout - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresourceRange); - - drawUI(drawCmdBuffers[i], frameBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void updateUniformBuffers() - { - uniformData.projInverse = glm::inverse(camera.matrices.perspective); - uniformData.viewInverse = glm::inverse(camera.matrices.view); - uniformData.lightPos = glm::vec4(cos(glm::radians(timer * 360.0f)) * 25.0f, 25.0f, 25.0f + sin(glm::radians(timer * 360.0f)) * 5.0f, 0.0f); - memcpy(ubo.mapped, &uniformData, sizeof(uniformData)); - } - - void getEnabledFeatures() - { - // Enable features required for ray tracing using feature chaining via pNext - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR; - enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE; - enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures; - - enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE; - enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures; - - // VK_KHR_ray_tracing_position_fetch has a new feature struct - enabledRayTracingPositionFetchFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR; - enabledRayTracingPositionFetchFeatures.rayTracingPositionFetch = VK_TRUE; - enabledRayTracingPositionFetchFeatures.pNext = &enabledAccelerationStructureFeatures; - - deviceCreatepNextChain = &enabledRayTracingPositionFetchFeatures; - } - - void prepare() - { - VulkanRaytracingSample::prepare(); - - // Create the acceleration structures used to render the ray traced scene - createBottomLevelAccelerationStructure(); - createTopLevelAccelerationStructure(); - - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - createUniformBuffer(); - createRayTracingPipeline(); - createShaderBindingTables(); - createDescriptors(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (!paused || camera.updated) - updateUniformBuffers(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/raytracingreflections/raytracingreflections.cpp b/examples/raytracingreflections/raytracingreflections.cpp deleted file mode 100644 index 82505113..00000000 --- a/examples/raytracingreflections/raytracingreflections.cpp +++ /dev/null @@ -1,584 +0,0 @@ -/* -* Vulkan Example - Hardware accelerated ray tracing example for doing reflections -* -* Renders a complex scene doing recursion inside the shaders for creating reflections -* -* Copyright (C) 2019-2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "VulkanRaytracingSample.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanRaytracingSample -{ -public: - AccelerationStructure bottomLevelAS{}; - AccelerationStructure topLevelAS{}; - - std::vector shaderGroups{}; - struct ShaderBindingTables { - ShaderBindingTable raygen; - ShaderBindingTable miss; - ShaderBindingTable hit; - } shaderBindingTables; - - struct UniformData { - glm::mat4 viewInverse; - glm::mat4 projInverse; - glm::vec4 lightPos; - int32_t vertexSize; - } uniformData; - vks::Buffer ubo; - - VkPipeline pipeline; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; - - vkglTF::Model scene; - - // This sample is derived from an extended base class that saves most of the ray tracing setup boiler plate - VulkanExample() : VulkanRaytracingSample() - { - title = "Ray tracing reflections"; - timerSpeed *= 0.5f; - camera.rotationSpeed *= 0.25f; - camera.type = Camera::CameraType::firstperson; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.5f, -2.0f)); - enableExtensions(); - } - - ~VulkanExample() - { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - deleteStorageImage(); - deleteAccelerationStructure(bottomLevelAS); - deleteAccelerationStructure(topLevelAS); - shaderBindingTables.raygen.destroy(); - shaderBindingTables.miss.destroy(); - shaderBindingTables.hit.destroy(); - ubo.destroy(); - } - - /* - Create the bottom level acceleration structure contains the scene's actual geometry (vertices, triangles) - */ - void createBottomLevelAccelerationStructure() - { - // Instead of a simple triangle, we'll be loading a more complex scene for this example - // The shaders are accessing the vertex and index buffers of the scene, so the proper usage flag has to be set on the vertex and index buffers for the scene - vkglTF::memoryPropertyFlags = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - scene.loadFromFile(getAssetPath() + "models/reflection_scene.gltf", vulkanDevice, queue, glTFLoadingFlags); - - VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{}; - - vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.vertices.buffer); - indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.indices.buffer); - - uint32_t numTriangles = static_cast(scene.indices.count) / 3; - - // Build - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; - accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.maxVertex = scene.vertices.count - 1; - accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(vkglTF::Vertex); - accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; - accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0; - accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &numTriangles, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(bottomLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the bottom level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = numTriangles; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - } - - /* - The top level acceleration structure contains the scene's object instances - */ - void createTopLevelAccelerationStructure() - { - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f }; - - VkAccelerationStructureInstanceKHR instance{}; - instance.transform = transformMatrix; - instance.instanceCustomIndex = 0; - instance.mask = 0xFF; - instance.instanceShaderBindingTableRecordOffset = 0; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = bottomLevelAS.deviceAddress; - - // Buffer for instance data - vks::Buffer instancesBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &instancesBuffer, - sizeof(VkAccelerationStructureInstanceKHR), - &instance)); - - VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{}; - instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer); - - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE; - accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - uint32_t primitive_count = 1; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &primitive_count, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(topLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the top level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = 1; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - instancesBuffer.destroy(); - } - - /* - Create the Shader Binding Tables that binds the programs and top-level acceleration structure - - SBT Layout used in this sample: - - /-----------\ - | raygen | - |-----------| - | miss | - |-----------| - | hit | - \-----------/ - - */ - void createShaderBindingTables() { - const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize; - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - const uint32_t groupCount = static_cast(shaderGroups.size()); - const uint32_t sbtSize = groupCount * handleSizeAligned; - - std::vector shaderHandleStorage(sbtSize); - VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data())); - - createShaderBindingTable(shaderBindingTables.raygen, 1); - createShaderBindingTable(shaderBindingTables.miss, 1); - createShaderBindingTable(shaderBindingTables.hit, 1); - - // Copy handles - memcpy(shaderBindingTables.raygen.mapped, shaderHandleStorage.data(), handleSize); - memcpy(shaderBindingTables.miss.mapped, shaderHandleStorage.data() + handleSizeAligned, handleSize); - memcpy(shaderBindingTables.hit.mapped, shaderHandleStorage.data() + handleSizeAligned * 2, handleSize); - } - - /* - Create the descriptor sets used for the ray tracing dispatch - */ - void createDescriptorSets() - { - std::vector poolSizes = { - { VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2 } - }; - VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool)); - - VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); - - VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks::initializers::writeDescriptorSetAccelerationStructureKHR(); - descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle; - - VkWriteDescriptorSet accelerationStructureWrite{}; - accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - // The specialized acceleration structure descriptor has to be chained - accelerationStructureWrite.pNext = &descriptorAccelerationStructureInfo; - accelerationStructureWrite.dstSet = descriptorSet; - accelerationStructureWrite.dstBinding = 0; - accelerationStructureWrite.descriptorCount = 1; - accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkDescriptorBufferInfo vertexBufferDescriptor{ scene.vertices.buffer, 0, VK_WHOLE_SIZE }; - VkDescriptorBufferInfo indexBufferDescriptor{ scene.indices.buffer, 0, VK_WHOLE_SIZE }; - - std::vector writeDescriptorSets = { - // Binding 0: Top level acceleration structure - accelerationStructureWrite, - // Binding 1: Ray tracing result image - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor), - // Binding 2: Uniform data - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor), - // Binding 3: Scene vertex buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &vertexBufferDescriptor), - // Binding 4: Scene index buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4, &indexBufferDescriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE); - } - - /* - Create our ray tracing pipeline - */ - void createRayTracingPipeline() - { - std::vector setLayoutBindings = { - // Binding 0: Acceleration structure - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0), - // Binding 1: Storage image - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_RAYGEN_BIT_KHR, 1), - // Binding 2: Uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR, 2), - // Binding 3: Vertex buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 3), - // Binding 4: Index buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 4), - }; - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pPipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCI, nullptr, &pipelineLayout)); - - /* - Setup ray tracing shader groups - */ - std::vector shaderStages; - - VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t)); - uint32_t maxRecursion = 4; - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(maxRecursion), &maxRecursion); - - // Ray generation group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingreflections/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR)); - // Pass recursion depth for reflections to ray generation shader via specialization constant - shaderStages.back().pSpecializationInfo = &specializationInfo; - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Miss group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingreflections/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Closest hit group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingreflections/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; - shaderGroup.generalShader = VK_SHADER_UNUSED_KHR; - shaderGroup.closestHitShader = static_cast(shaderStages.size()) - 1; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR(); - rayTracingPipelineCI.stageCount = static_cast(shaderStages.size()); - rayTracingPipelineCI.pStages = shaderStages.data(); - rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size()); - rayTracingPipelineCI.pGroups = shaderGroups.data(); - rayTracingPipelineCI.maxPipelineRayRecursionDepth = std::min(uint32_t(4), rayTracingPipelineProperties.maxRayRecursionDepth); - rayTracingPipelineCI.layout = pipelineLayout; - VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline)); - } - - /* - Create the uniform buffer used to pass matrices to the ray tracing ray generation shader - */ - void createUniformBuffer() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &ubo, - sizeof(uniformData), - &uniformData)); - VK_CHECK_RESULT(ubo.map()); - - updateUniformBuffers(); - } - - /* - If the window has been resized, we need to recreate the storage image and it's descriptor - */ - void handleResize() - { - // Recreate image - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - // Update descriptor - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - vkUpdateDescriptorSets(device, 1, &resultImageWrite, 0, VK_NULL_HANDLE); - resized = false; - } - - /* - Command buffer generation - */ - void buildCommandBuffers() - { - if (resized) - { - handleResize(); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0); - - /* - Dispatch the ray tracing commands - */ - VkStridedDeviceAddressRegionKHR emptySbtEntry = {}; - vkCmdTraceRaysKHR( - drawCmdBuffers[i], - &shaderBindingTables.raygen.stridedDeviceAddressRegion, - &shaderBindingTables.miss.stridedDeviceAddressRegion, - &shaderBindingTables.hit.stridedDeviceAddressRegion, - &emptySbtEntry, - width, - height, - 1); - - /* - Copy ray tracing output to swap chain image - */ - - // Prepare current swap chain image as transfer destination - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Prepare ray tracing output image as transfer source - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresourceRange); - - VkImageCopy copyRegion{}; - copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.srcOffset = { 0, 0, 0 }; - copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.dstOffset = { 0, 0, 0 }; - copyRegion.extent = { width, height, 1 }; - vkCmdCopyImage(drawCmdBuffers[i], storageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChain.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - // Transition swap chain image back for presentation - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresourceRange); - - // Transition ray tracing output image back to general layout - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresourceRange); - - drawUI(drawCmdBuffers[i], frameBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void updateUniformBuffers() - { - uniformData.projInverse = glm::inverse(camera.matrices.perspective); - uniformData.viewInverse = glm::inverse(camera.matrices.view); - uniformData.lightPos = glm::vec4(cos(glm::radians(timer * 360.0f)) * 40.0f, -20.0f + sin(glm::radians(timer * 360.0f)) * 20.0f, 25.0f + sin(glm::radians(timer * 360.0f)) * 5.0f, 0.0f); - // Pass the vertex size to the shader for unpacking vertices - uniformData.vertexSize = sizeof(vkglTF::Vertex); - memcpy(ubo.mapped, &uniformData, sizeof(uniformData)); - } - - void getEnabledFeatures() - { - // Enable features required for ray tracing using feature chaining via pNext - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR; - enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE; - enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures; - - enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE; - enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures; - - deviceCreatepNextChain = &enabledAccelerationStructureFeatures; - } - - void prepare() - { - VulkanRaytracingSample::prepare(); - - // Create the acceleration structures used to render the ray traced scene - createBottomLevelAccelerationStructure(); - createTopLevelAccelerationStructure(); - - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - createUniformBuffer(); - createRayTracingPipeline(); - createShaderBindingTables(); - createDescriptorSets(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (!paused || camera.updated) - updateUniformBuffers(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/raytracingsbtdata/raytracingsbtdata.cpp b/examples/raytracingsbtdata/raytracingsbtdata.cpp deleted file mode 100644 index 46739460..00000000 --- a/examples/raytracingsbtdata/raytracingsbtdata.cpp +++ /dev/null @@ -1,937 +0,0 @@ -/* -* Vulkan Example - Hardware accelerated ray tracing example using SBT data -* -* Uses the data section of each shader binding table record to color the background and geometry -* -* Example by Nate Morrical (https://github.com/natevm) -* -* Copyright (C) 2019-2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -// Holds data for a ray tracing scratch buffer that is used as a temporary storage -struct RayTracingScratchBuffer -{ - uint64_t deviceAddress{ 0 }; - VkBuffer handle{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; -}; - -// Ray tracing acceleration structure -struct AccelerationStructure { - VkAccelerationStructureKHR handle; - uint64_t deviceAddress{ 0 }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - VkBuffer buffer; -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR{ VK_NULL_HANDLE }; - PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR{ VK_NULL_HANDLE }; - PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR{ VK_NULL_HANDLE }; - PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR{ VK_NULL_HANDLE }; - PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR{ VK_NULL_HANDLE }; - PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR{ VK_NULL_HANDLE }; - PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR{ VK_NULL_HANDLE }; - PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR{ VK_NULL_HANDLE }; - PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR{ VK_NULL_HANDLE }; - PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR{ VK_NULL_HANDLE }; - - VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingPipelineProperties{}; - VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeatures{}; - - VkPhysicalDeviceBufferDeviceAddressFeatures enabledBufferDeviceAddresFeatures{}; - VkPhysicalDeviceRayTracingPipelineFeaturesKHR enabledRayTracingPipelineFeatures{}; - VkPhysicalDeviceAccelerationStructureFeaturesKHR enabledAccelerationStructureFeatures{}; - - AccelerationStructure bottomLevelAS{}; - AccelerationStructure topLevelAS{}; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount{ 0 }; - vks::Buffer transformBuffer; - std::vector shaderGroups{}; - vks::Buffer raygenShaderBindingTable; - vks::Buffer missShaderBindingTable; - vks::Buffer hitShaderBindingTable; - - struct StorageImage { - VkDeviceMemory memory; - VkImage image; - VkImageView view; - VkFormat format; - } storageImage{}; - - struct UniformData { - glm::mat4 viewInverse; - glm::mat4 projInverse; - } uniformData; - vks::Buffer ubo; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Ray tracing SBT data"; - settings.overlay = false; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -2.5f)); - - // Require Vulkan 1.1 - apiVersion = VK_API_VERSION_1_1; - - // Ray tracing related extensions required by this sample - enabledDeviceExtensions.push_back(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME); - - // Required by VK_KHR_acceleration_structure - enabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - - // Required for VK_KHR_ray_tracing_pipeline - enabledDeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); - - // Required by VK_KHR_spirv_1_4 - enabledDeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); - } - - ~VulkanExample() - { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyImageView(device, storageImage.view, nullptr); - vkDestroyImage(device, storageImage.image, nullptr); - vkFreeMemory(device, storageImage.memory, nullptr); - vkFreeMemory(device, bottomLevelAS.memory, nullptr); - vkDestroyBuffer(device, bottomLevelAS.buffer, nullptr); - vkDestroyAccelerationStructureKHR(device, bottomLevelAS.handle, nullptr); - vkFreeMemory(device, topLevelAS.memory, nullptr); - vkDestroyBuffer(device, topLevelAS.buffer, nullptr); - vkDestroyAccelerationStructureKHR(device, topLevelAS.handle, nullptr); - vertexBuffer.destroy(); - indexBuffer.destroy(); - transformBuffer.destroy(); - raygenShaderBindingTable.destroy(); - missShaderBindingTable.destroy(); - hitShaderBindingTable.destroy(); - ubo.destroy(); - } - - /* - Create a scratch buffer to hold temporary data for a ray tracing acceleration structure - */ - RayTracingScratchBuffer createScratchBuffer(VkDeviceSize size) - { - RayTracingScratchBuffer scratchBuffer{}; - - VkBufferCreateInfo bufferCreateInfo{}; - bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferCreateInfo.size = size; - bufferCreateInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &scratchBuffer.handle)); - - VkMemoryRequirements memoryRequirements{}; - vkGetBufferMemoryRequirements(device, scratchBuffer.handle, &memoryRequirements); - - VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{}; - memoryAllocateFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; - memoryAllocateFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; - - VkMemoryAllocateInfo memoryAllocateInfo = {}; - memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memoryAllocateInfo.pNext = &memoryAllocateFlagsInfo; - memoryAllocateInfo.allocationSize = memoryRequirements.size; - memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &scratchBuffer.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, scratchBuffer.handle, scratchBuffer.memory, 0)); - - VkBufferDeviceAddressInfoKHR bufferDeviceAddressInfo{}; - bufferDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; - bufferDeviceAddressInfo.buffer = scratchBuffer.handle; - scratchBuffer.deviceAddress = vkGetBufferDeviceAddressKHR(device, &bufferDeviceAddressInfo); - - return scratchBuffer; - } - - void deleteScratchBuffer(RayTracingScratchBuffer& scratchBuffer) - { - if (scratchBuffer.memory != VK_NULL_HANDLE) { - vkFreeMemory(device, scratchBuffer.memory, nullptr); - } - if (scratchBuffer.handle != VK_NULL_HANDLE) { - vkDestroyBuffer(device, scratchBuffer.handle, nullptr); - } - } - - void createAccelerationStructureBuffer(AccelerationStructure &accelerationStructure, VkAccelerationStructureBuildSizesInfoKHR buildSizeInfo) - { - VkBufferCreateInfo bufferCreateInfo{}; - bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferCreateInfo.size = buildSizeInfo.accelerationStructureSize; - bufferCreateInfo.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &accelerationStructure.buffer)); - VkMemoryRequirements memoryRequirements{}; - vkGetBufferMemoryRequirements(device, accelerationStructure.buffer, &memoryRequirements); - VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{}; - memoryAllocateFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; - memoryAllocateFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; - VkMemoryAllocateInfo memoryAllocateInfo{}; - memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memoryAllocateInfo.pNext = &memoryAllocateFlagsInfo; - memoryAllocateInfo.allocationSize = memoryRequirements.size; - memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &accelerationStructure.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, accelerationStructure.buffer, accelerationStructure.memory, 0)); - } - - - /* - Gets the device address from a buffer that's required for some of the buffers used for ray tracing - */ - uint64_t getBufferDeviceAddress(VkBuffer buffer) - { - VkBufferDeviceAddressInfoKHR bufferDeviceAI{}; - bufferDeviceAI.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; - bufferDeviceAI.buffer = buffer; - return vkGetBufferDeviceAddressKHR(device, &bufferDeviceAI); - } - - /* - Set up a storage image that the ray generation shader will be writing to - */ - void createStorageImage() - { - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = swapChain.colorFormat; - image.extent.width = width; - image.extent.height = height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT; - image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &storageImage.image)); - - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, storageImage.image, &memReqs); - VkMemoryAllocateInfo memoryAllocateInfo = vks::initializers::memoryAllocateInfo(); - memoryAllocateInfo.allocationSize = memReqs.size; - memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &storageImage.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, storageImage.image, storageImage.memory, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = swapChain.colorFormat; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = storageImage.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &storageImage.view)); - - VkCommandBuffer cmdBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout(cmdBuffer, storageImage.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_GENERAL, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - vulkanDevice->flushCommandBuffer(cmdBuffer, queue); - } - - /* - Create the bottom level acceleration structure contains the scene's actual geometry (vertices, triangles) - */ - void createBottomLevelAccelerationStructure() - { - // Setup vertices for a single triangle - struct Vertex { - float pos[3]; - }; - std::vector vertices = { - { { 1.0f, 1.0f, 0.0f } }, - { { -1.0f, 1.0f, 0.0f } }, - { { 0.0f, -1.0f, 0.0f } } - }; - - // Setup indices - std::vector indices = { 0, 1, 2 }; - indexCount = static_cast(indices.size()); - - // Setup identity transform matrix - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f - }; - - // Create buffers - // For the sake of simplicity we won't stage the vertex data to the GPU memory - // Vertex buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &vertexBuffer, - vertices.size() * sizeof(Vertex), - vertices.data())); - // Index buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &indexBuffer, - indices.size() * sizeof(uint32_t), - indices.data())); - // Transform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &transformBuffer, - sizeof(VkTransformMatrixKHR), - &transformMatrix)); - - VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR transformBufferDeviceAddress{}; - - vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(vertexBuffer.buffer); - indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(indexBuffer.buffer); - transformBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(transformBuffer.buffer); - - // Build - VkAccelerationStructureGeometryKHR accelerationStructureGeometry{}; - accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; - accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.maxVertex = 3; - accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(Vertex); - accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; - accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0; - accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr; - accelerationStructureGeometry.geometry.triangles.transformData = transformBufferDeviceAddress; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{}; - accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - const uint32_t numTriangles = 1; - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{}; - accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &numTriangles, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructureBuffer(bottomLevelAS, accelerationStructureBuildSizesInfo); - - VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{}; - accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - accelerationStructureCreateInfo.buffer = bottomLevelAS.buffer; - accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize; - accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &bottomLevelAS.handle); - - // Create a small scratch buffer used during build of the bottom level acceleration structure - RayTracingScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{}; - accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = numTriangles; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{}; - accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; - accelerationDeviceAddressInfo.accelerationStructure = bottomLevelAS.handle; - bottomLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo); - - deleteScratchBuffer(scratchBuffer); - } - - /* - The top level acceleration structure contains the scene's object instances - */ - void createTopLevelAccelerationStructure() - { - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f }; - - VkAccelerationStructureInstanceKHR instance{}; - instance.transform = transformMatrix; - instance.instanceCustomIndex = 0; - instance.mask = 0xFF; - instance.instanceShaderBindingTableRecordOffset = 0; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = bottomLevelAS.deviceAddress; - - // Buffer for instance data - vks::Buffer instancesBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &instancesBuffer, - sizeof(VkAccelerationStructureInstanceKHR), - &instance)); - - VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{}; - instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer); - - VkAccelerationStructureGeometryKHR accelerationStructureGeometry{}; - accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE; - accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress; - - // Get size info - /* - The pSrcAccelerationStructure, dstAccelerationStructure, and mode members of pBuildInfo are ignored. Any VkDeviceOrHostAddressKHR members of pBuildInfo are ignored by this command, except that the hostAddress member of VkAccelerationStructureGeometryTrianglesDataKHR::transformData will be examined to check if it is NULL.* - */ - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{}; - accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - uint32_t primitive_count = 1; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{}; - accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &primitive_count, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructureBuffer(topLevelAS, accelerationStructureBuildSizesInfo); - - VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{}; - accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - accelerationStructureCreateInfo.buffer = topLevelAS.buffer; - accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize; - accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &topLevelAS.handle); - - // Create a small scratch buffer used during build of the top level acceleration structure - RayTracingScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{}; - accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = 1; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{}; - accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; - accelerationDeviceAddressInfo.accelerationStructure = topLevelAS.handle; - topLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo); - - deleteScratchBuffer(scratchBuffer); - instancesBuffer.destroy(); - } - - /* - Create the Shader Binding Tables that binds the programs and top-level acceleration structure - In this example, we embed data in each record that can be read by the device during ray tracing - - SBT Layout used in this sample: - - /----------------\ - | raygen handle | - | - - - - - - - | - | raygen data | - |----------------| - | miss handle | - | - - - - - - - | - | miss data | - |----------------| - | hit handle | - | - - - - - - - | - | hit data | - \----------------/ - - */ - void createShaderBindingTable() { - const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize; - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - const uint32_t groupCount = static_cast(shaderGroups.size()); - const uint32_t sbtSize = groupCount * handleSizeAligned; - - std::vector shaderHandleStorage(sbtSize); - VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data())); - - const VkBufferUsageFlags bufferUsageFlags = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - const VkMemoryPropertyFlags memoryUsageFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - - // We allocate space for the handle (which is like lambda function pointers to call in the ray tracing pipeline) - // as well as the data to pass to those functions (which act as the variables being "captured" by those lambda functions) - uint32_t bufferSize = vks::tools::alignedSize(handleSize + 3 * sizeof(float), rayTracingPipelineProperties.shaderGroupBaseAlignment); - VK_CHECK_RESULT(vulkanDevice->createBuffer(bufferUsageFlags, memoryUsageFlags, &raygenShaderBindingTable, bufferSize)); - VK_CHECK_RESULT(vulkanDevice->createBuffer(bufferUsageFlags, memoryUsageFlags, &missShaderBindingTable, bufferSize)); - VK_CHECK_RESULT(vulkanDevice->createBuffer(bufferUsageFlags, memoryUsageFlags, &hitShaderBindingTable, bufferSize)); - - // Copy handles - raygenShaderBindingTable.map(); - missShaderBindingTable.map(); - hitShaderBindingTable.map(); - memcpy(raygenShaderBindingTable.mapped, shaderHandleStorage.data(), handleSize); - memcpy(missShaderBindingTable.mapped, shaderHandleStorage.data() + handleSizeAligned, handleSize); - memcpy(hitShaderBindingTable.mapped, shaderHandleStorage.data() + handleSizeAligned * 2, handleSize); - - // Copy over raygen record data - glm::vec3 color1(0.5f, 0.5f, 0.5f); - memcpy(((uint8_t*)(raygenShaderBindingTable.mapped)) + handleSize, &color1, sizeof(glm::vec3)); - - // Copy over miss record data - glm::vec3 color2(1.f, 1.f, 1.f); - memcpy(((uint8_t*)(missShaderBindingTable.mapped)) + handleSize, &color2, sizeof(glm::vec3)); - - // Copy over hit group record data - glm::vec3 color3(1.f, 0.f, 0.f); - memcpy(((uint8_t*)(hitShaderBindingTable.mapped)) + handleSize, &color3, sizeof(glm::vec3)); - } - - /* - Create the descriptor sets used for the ray tracing dispatch - */ - void createDescriptorSets() - { - std::vector poolSizes = { - { VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 } - }; - VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool)); - - VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); - - VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo{}; - descriptorAccelerationStructureInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; - descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle; - - VkWriteDescriptorSet accelerationStructureWrite{}; - accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - // The specialized acceleration structure descriptor has to be chained - accelerationStructureWrite.pNext = &descriptorAccelerationStructureInfo; - accelerationStructureWrite.dstSet = descriptorSet; - accelerationStructureWrite.dstBinding = 0; - accelerationStructureWrite.descriptorCount = 1; - accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - - VkDescriptorImageInfo storageImageDescriptor{}; - storageImageDescriptor.imageView = storageImage.view; - storageImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - VkWriteDescriptorSet uniformBufferWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor); - - std::vector writeDescriptorSets = { - accelerationStructureWrite, - resultImageWrite, - uniformBufferWrite - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE); - } - - /* - Create our ray tracing pipeline - */ - void createRayTracingPipeline() - { - VkDescriptorSetLayoutBinding accelerationStructureLayoutBinding{}; - accelerationStructureLayoutBinding.binding = 0; - accelerationStructureLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - accelerationStructureLayoutBinding.descriptorCount = 1; - accelerationStructureLayoutBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR; - - VkDescriptorSetLayoutBinding resultImageLayoutBinding{}; - resultImageLayoutBinding.binding = 1; - resultImageLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - resultImageLayoutBinding.descriptorCount = 1; - resultImageLayoutBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR; - - VkDescriptorSetLayoutBinding uniformBufferBinding{}; - uniformBufferBinding.binding = 2; - uniformBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - uniformBufferBinding.descriptorCount = 1; - uniformBufferBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR; - - std::vector bindings({ - accelerationStructureLayoutBinding, - resultImageLayoutBinding, - uniformBufferBinding - }); - - VkDescriptorSetLayoutCreateInfo descriptorSetlayoutCI{}; - descriptorSetlayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptorSetlayoutCI.bindingCount = static_cast(bindings.size()); - descriptorSetlayoutCI.pBindings = bindings.data(); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetlayoutCI, nullptr, &descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pipelineLayoutCI{}; - pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutCI.setLayoutCount = 1; - pipelineLayoutCI.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - /* - Setup ray tracing shader groups - */ - std::vector shaderStages; - - // Ray generation group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingsbtdata/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Miss group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingsbtdata/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Closest hit group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingsbtdata/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; - shaderGroup.generalShader = VK_SHADER_UNUSED_KHR; - shaderGroup.closestHitShader = static_cast(shaderStages.size()) - 1; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - /* - Create the ray tracing pipeline - */ - VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI{}; - rayTracingPipelineCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; - rayTracingPipelineCI.stageCount = static_cast(shaderStages.size()); - rayTracingPipelineCI.pStages = shaderStages.data(); - rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size()); - rayTracingPipelineCI.pGroups = shaderGroups.data(); - rayTracingPipelineCI.maxPipelineRayRecursionDepth = 1; - rayTracingPipelineCI.layout = pipelineLayout; - VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline)); - } - - /* - Create the uniform buffer used to pass matrices to the ray tracing ray generation shader - */ - void createUniformBuffer() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &ubo, - sizeof(uniformData), - &uniformData)); - VK_CHECK_RESULT(ubo.map()); - - updateUniformBuffers(); - } - - /* - If the window has been resized, we need to recreate the storage image and it's descriptor - */ - void handleResize() - { - // Delete allocated resources - vkDestroyImageView(device, storageImage.view, nullptr); - vkDestroyImage(device, storageImage.image, nullptr); - vkFreeMemory(device, storageImage.memory, nullptr); - // Recreate image - createStorageImage(); - // Update descriptor - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - vkUpdateDescriptorSets(device, 1, &resultImageWrite, 0, VK_NULL_HANDLE); - } - - /* - Command buffer generation - */ - void buildCommandBuffers() - { - if (resized) - { - handleResize(); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Setup the buffer regions pointing to the shaders in our shader binding table - */ - - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - - // Note, we add 3 * sizeof(float) to each SBT entry size to account for the data sections of these records - // that we use to store our color data - VkStridedDeviceAddressRegionKHR raygenShaderSbtEntry{}; - raygenShaderSbtEntry.deviceAddress = getBufferDeviceAddress(raygenShaderBindingTable.buffer); - raygenShaderSbtEntry.size = vks::tools::alignedSize(handleSizeAligned + 3 * sizeof(float), rayTracingPipelineProperties.shaderGroupBaseAlignment); - raygenShaderSbtEntry.stride = raygenShaderSbtEntry.size; - - VkStridedDeviceAddressRegionKHR missShaderSbtEntry{}; - missShaderSbtEntry.deviceAddress = getBufferDeviceAddress(missShaderBindingTable.buffer); - missShaderSbtEntry.size = vks::tools::alignedSize(handleSizeAligned + 3 * sizeof(float), rayTracingPipelineProperties.shaderGroupBaseAlignment); - missShaderSbtEntry.stride = missShaderSbtEntry.size; - - VkStridedDeviceAddressRegionKHR hitShaderSbtEntry{}; - hitShaderSbtEntry.deviceAddress = getBufferDeviceAddress(hitShaderBindingTable.buffer); - hitShaderSbtEntry.size = vks::tools::alignedSize(handleSizeAligned + 3 * sizeof(float), rayTracingPipelineProperties.shaderGroupBaseAlignment); - hitShaderSbtEntry.stride = hitShaderSbtEntry.size; - - VkStridedDeviceAddressRegionKHR callableShaderSbtEntry{}; - - /* - Dispatch the ray tracing commands - */ - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0); - - vkCmdTraceRaysKHR( - drawCmdBuffers[i], - &raygenShaderSbtEntry, - &missShaderSbtEntry, - &hitShaderSbtEntry, - &callableShaderSbtEntry, - width, - height, - 1); - - /* - Copy ray tracing output to swap chain image - */ - - // Prepare current swap chain image as transfer destination - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Prepare ray tracing output image as transfer source - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresourceRange); - - VkImageCopy copyRegion{}; - copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.srcOffset = { 0, 0, 0 }; - copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.dstOffset = { 0, 0, 0 }; - copyRegion.extent = { width, height, 1 }; - vkCmdCopyImage(drawCmdBuffers[i], storageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChain.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - // Transition swap chain image back for presentation - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresourceRange); - - // Transition ray tracing output image back to general layout - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresourceRange); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void updateUniformBuffers() - { - uniformData.projInverse = glm::inverse(camera.matrices.perspective); - uniformData.viewInverse = glm::inverse(camera.matrices.view); - memcpy(ubo.mapped, &uniformData, sizeof(uniformData)); - } - - void getEnabledFeatures() - { - // Enable features required for ray tracing using feature chaining via pNext - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR; - enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE; - enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures; - - enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE; - enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures; - - deviceCreatepNextChain = &enabledAccelerationStructureFeatures; - } - - void prepare() - { - VulkanExampleBase::prepare(); - - // Get ray tracing pipeline properties, which will be used later on in the sample - rayTracingPipelineProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR; - VkPhysicalDeviceProperties2 deviceProperties2{}; - deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - deviceProperties2.pNext = &rayTracingPipelineProperties; - vkGetPhysicalDeviceProperties2(physicalDevice, &deviceProperties2); - - // Get acceleration structure properties, which will be used later on in the sample - accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - VkPhysicalDeviceFeatures2 deviceFeatures2{}; - deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - deviceFeatures2.pNext = &accelerationStructureFeatures; - vkGetPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures2); - - // Get the ray tracing and accelertion structure related function pointers required by this sample - vkGetBufferDeviceAddressKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR")); - vkCmdBuildAccelerationStructuresKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR")); - vkBuildAccelerationStructuresKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR")); - vkCreateAccelerationStructureKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR")); - vkDestroyAccelerationStructureKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR")); - vkGetAccelerationStructureBuildSizesKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureBuildSizesKHR")); - vkGetAccelerationStructureDeviceAddressKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR")); - vkCmdTraceRaysKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR")); - vkGetRayTracingShaderGroupHandlesKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR")); - vkCreateRayTracingPipelinesKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR")); - - // Create the acceleration structures used to render the ray traced scene - createBottomLevelAccelerationStructure(); - createTopLevelAccelerationStructure(); - - createStorageImage(); - createUniformBuffer(); - createRayTracingPipeline(); - createShaderBindingTable(); - createDescriptorSets(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (camera.updated) - updateUniformBuffers(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/raytracingshadows/raytracingshadows.cpp b/examples/raytracingshadows/raytracingshadows.cpp deleted file mode 100644 index 24825e96..00000000 --- a/examples/raytracingshadows/raytracingshadows.cpp +++ /dev/null @@ -1,584 +0,0 @@ -/* -* Vulkan Example - Hardware accelerated ray tracing shadow example -* -* Renders a complex scene using multiple hit and miss shaders for implementing shadows -* -* Copyright (C) by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "VulkanRaytracingSample.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanRaytracingSample -{ -public: - AccelerationStructure bottomLevelAS; - AccelerationStructure topLevelAS; - - std::vector shaderGroups{}; - struct ShaderBindingTables { - ShaderBindingTable raygen; - ShaderBindingTable miss; - ShaderBindingTable hit; - } shaderBindingTables; - - struct UniformData { - glm::mat4 viewInverse; - glm::mat4 projInverse; - glm::vec4 lightPos; - int32_t vertexSize; - } uniformData; - vks::Buffer ubo; - - VkPipeline pipeline; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; - - vkglTF::Model scene; - - // This sample is derived from an extended base class that saves most of the ray tracing setup boiler plate - VulkanExample() : VulkanRaytracingSample() - { - title = "Ray traced shadows"; - timerSpeed *= 0.25f; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 3.0f, -10.0f)); - enableExtensions(); - } - - ~VulkanExample() - { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - deleteStorageImage(); - deleteAccelerationStructure(bottomLevelAS); - deleteAccelerationStructure(topLevelAS); - shaderBindingTables.raygen.destroy(); - shaderBindingTables.miss.destroy(); - shaderBindingTables.hit.destroy(); - ubo.destroy(); - } - - /* - Create the bottom level acceleration structure contains the scene's actual geometry (vertices, triangles) - */ - void createBottomLevelAccelerationStructure() - { - // Instead of a simple triangle, we'll be loading a more complex scene for this example - // The shaders are accessing the vertex and index buffers of the scene, so the proper usage flag has to be set on the vertex and index buffers for the scene - vkglTF::memoryPropertyFlags = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - scene.loadFromFile(getAssetPath() + "models/vulkanscene_shadow.gltf", vulkanDevice, queue, glTFLoadingFlags); - - VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{}; - - vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.vertices.buffer); - indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.indices.buffer); - - uint32_t numTriangles = static_cast(scene.indices.count) / 3; - - // Build - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; - accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.maxVertex = scene.vertices.count - 1; - accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(vkglTF::Vertex); - accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; - accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0; - accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &numTriangles, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(bottomLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the bottom level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = numTriangles; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - } - - /* - The top level acceleration structure contains the scene's object instances - */ - void createTopLevelAccelerationStructure() - { - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f }; - - VkAccelerationStructureInstanceKHR instance{}; - instance.transform = transformMatrix; - instance.instanceCustomIndex = 0; - instance.mask = 0xFF; - instance.instanceShaderBindingTableRecordOffset = 0; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = bottomLevelAS.deviceAddress; - - // Buffer for instance data - vks::Buffer instancesBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &instancesBuffer, - sizeof(VkAccelerationStructureInstanceKHR), - &instance)); - - VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{}; - instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer); - - VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR(); - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE; - accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - uint32_t primitive_count = 1; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR(); - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &primitive_count, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructure(topLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, accelerationStructureBuildSizesInfo); - - // Create a small scratch buffer used during build of the top level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR(); - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = 1; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - deleteScratchBuffer(scratchBuffer); - instancesBuffer.destroy(); - } - - - /* - Create the Shader Binding Tables that binds the programs and top-level acceleration structure - - SBT Layout used in this sample: - - /-----------\ - | raygen | - |-----------| - | miss | - |-----------| - | hit | - \-----------/ - - */ - void createShaderBindingTables() { - const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize; - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - const uint32_t groupCount = static_cast(shaderGroups.size()); - const uint32_t sbtSize = groupCount * handleSizeAligned; - - std::vector shaderHandleStorage(sbtSize); - VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data())); - - createShaderBindingTable(shaderBindingTables.raygen, 1); - // We are using two miss shaders - createShaderBindingTable(shaderBindingTables.miss, 2); - createShaderBindingTable(shaderBindingTables.hit, 1); - - // Copy handles - memcpy(shaderBindingTables.raygen.mapped, shaderHandleStorage.data(), handleSize); - // We are using two miss shaders, so we need to get two handles for the miss shader binding table - memcpy(shaderBindingTables.miss.mapped, shaderHandleStorage.data() + handleSizeAligned, handleSize * 2); - memcpy(shaderBindingTables.hit.mapped, shaderHandleStorage.data() + handleSizeAligned * 3, handleSize); - } - - /* - Create the descriptor sets used for the ray tracing dispatch - */ - void createDescriptorSets() - { - std::vector poolSizes = { - { VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2 } - }; - VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool)); - - VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); - - VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks::initializers::writeDescriptorSetAccelerationStructureKHR(); - descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle; - - VkWriteDescriptorSet accelerationStructureWrite{}; - accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - // The specialized acceleration structure descriptor has to be chained - accelerationStructureWrite.pNext = &descriptorAccelerationStructureInfo; - accelerationStructureWrite.dstSet = descriptorSet; - accelerationStructureWrite.dstBinding = 0; - accelerationStructureWrite.descriptorCount = 1; - accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkDescriptorBufferInfo vertexBufferDescriptor{ scene.vertices.buffer, 0, VK_WHOLE_SIZE }; - VkDescriptorBufferInfo indexBufferDescriptor{ scene.indices.buffer, 0, VK_WHOLE_SIZE }; - - std::vector writeDescriptorSets = { - // Binding 0: Top level acceleration structure - accelerationStructureWrite, - // Binding 1: Ray tracing result image - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor), - // Binding 2: Uniform data - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor), - // Binding 3: Scene vertex buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &vertexBufferDescriptor), - // Binding 4: Scene index buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4, &indexBufferDescriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE); - } - - /* - Create our ray tracing pipeline - */ - void createRayTracingPipeline() - { - std::vector setLayoutBindings = { - // Binding 0: Acceleration structure - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0), - // Binding 1: Storage image - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_RAYGEN_BIT_KHR, 1), - // Binding 2: Uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR, 2), - // Binding 3: Vertex buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 3), - // Binding 4: Index buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 4), - }; - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pPipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCI, nullptr, &pipelineLayout)); - - /* - Setup ray tracing shader groups - */ - std::vector shaderStages; - - // Ray generation group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingshadows/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Miss group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingshadows/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - // Second shader for shadows - shaderStages.push_back(loadShader(getShadersPath() + "raytracingshadows/shadow.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroups.push_back(shaderGroup); - } - - // Closest hit group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingshadows/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; - shaderGroup.generalShader = VK_SHADER_UNUSED_KHR; - shaderGroup.closestHitShader = static_cast(shaderStages.size()) - 1; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR(); - rayTracingPipelineCI.stageCount = static_cast(shaderStages.size()); - rayTracingPipelineCI.pStages = shaderStages.data(); - rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size()); - rayTracingPipelineCI.pGroups = shaderGroups.data(); - rayTracingPipelineCI.maxPipelineRayRecursionDepth = std::min(uint32_t(2), rayTracingPipelineProperties.maxRayRecursionDepth); - rayTracingPipelineCI.layout = pipelineLayout; - VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline)); - } - - /* - Create the uniform buffer used to pass matrices to the ray tracing ray generation shader - */ - void createUniformBuffer() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &ubo, - sizeof(uniformData), - &uniformData)); - VK_CHECK_RESULT(ubo.map()); - - updateUniformBuffers(); - } - - /* - If the window has been resized, we need to recreate the storage image and it's descriptor - */ - void handleResize() - { - // Recreate image - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - // Update descriptor - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - vkUpdateDescriptorSets(device, 1, &resultImageWrite, 0, VK_NULL_HANDLE); - resized = false; - } - - /* - Command buffer generation - */ - void buildCommandBuffers() - { - if (resized) - { - handleResize(); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Dispatch the ray tracing commands - */ - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0); - - VkStridedDeviceAddressRegionKHR emptySbtEntry = {}; - vkCmdTraceRaysKHR( - drawCmdBuffers[i], - &shaderBindingTables.raygen.stridedDeviceAddressRegion, - &shaderBindingTables.miss.stridedDeviceAddressRegion, - &shaderBindingTables.hit.stridedDeviceAddressRegion, - &emptySbtEntry, - width, - height, - 1); - - /* - Copy ray tracing output to swap chain image - */ - - // Prepare current swap chain image as transfer destination - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Prepare ray tracing output image as transfer source - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresourceRange); - - VkImageCopy copyRegion{}; - copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.srcOffset = { 0, 0, 0 }; - copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.dstOffset = { 0, 0, 0 }; - copyRegion.extent = { width, height, 1 }; - vkCmdCopyImage(drawCmdBuffers[i], storageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChain.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - // Transition swap chain image back for presentation - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresourceRange); - - // Transition ray tracing output image back to general layout - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresourceRange); - - drawUI(drawCmdBuffers[i], frameBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void updateUniformBuffers() - { - uniformData.projInverse = glm::inverse(camera.matrices.perspective); - uniformData.viewInverse = glm::inverse(camera.matrices.view); - uniformData.lightPos = glm::vec4(cos(glm::radians(timer * 360.0f)) * 40.0f, -50.0f + sin(glm::radians(timer * 360.0f)) * 20.0f, 25.0f + sin(glm::radians(timer * 360.0f)) * 5.0f, 0.0f); - // Pass the vertex size to the shader for unpacking vertices - uniformData.vertexSize = sizeof(vkglTF::Vertex); - memcpy(ubo.mapped, &uniformData, sizeof(uniformData)); - } - - void getEnabledFeatures() - { - // Enable features required for ray tracing using feature chaining via pNext - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR; - enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE; - enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures; - - enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE; - enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures; - - deviceCreatepNextChain = &enabledAccelerationStructureFeatures; - } - - void prepare() - { - VulkanRaytracingSample::prepare(); - - // Create the acceleration structures used to render the ray traced scene - createBottomLevelAccelerationStructure(); - createTopLevelAccelerationStructure(); - - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - createUniformBuffer(); - createRayTracingPipeline(); - createShaderBindingTables(); - createDescriptorSets(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (!paused || camera.updated) - updateUniformBuffers(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/raytracingtextures/raytracingtextures.cpp b/examples/raytracingtextures/raytracingtextures.cpp deleted file mode 100644 index 28a540a2..00000000 --- a/examples/raytracingtextures/raytracingtextures.cpp +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Vulkan Example - Texture mapping with transparency using accelerated ray tracing example - * - * Copyright (C) 2024 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -/* - * This hardware accelerated ray tracing sample renders a texture mapped quad with transparency - * The sample also makes use of buffer device addresses to pass references for vertex and index buffers - * to the shader, making data access a bit more straightforward than using descriptors. - * Buffer references themselves are then simply set at draw time using push constants. - * In addition to a closest hit shader, that now samples from the texture, an any hit shader is - * added to the closest hit shader group. We use this shader to check if the texel we want to - * sample at the currently hit ray position is transparent, and if that's the case the any hit - * shader will cancel the intersection. - */ - -#include "VulkanRaytracingSample.h" - -class VulkanExample : public VulkanRaytracingSample -{ -public: - AccelerationStructure bottomLevelAS{}; - AccelerationStructure topLevelAS{}; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount{ 0 }; - vks::Buffer transformBuffer; - std::vector shaderGroups{}; - struct ShaderBindingTables { - ShaderBindingTable raygen; - ShaderBindingTable miss; - ShaderBindingTable hit; - } shaderBindingTables; - - vks::Texture2D texture; - - struct UniformData { - glm::mat4 viewInverse; - glm::mat4 projInverse; - } uniformData; - vks::Buffer ubo; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanRaytracingSample() - { - title = "Ray tracing textures"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(45.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f)); - enableExtensions(); - // Buffer device address requires the 64-bit integer feature to be enabled - enabledFeatures.shaderInt64 = VK_TRUE; - } - - ~VulkanExample() - { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - deleteStorageImage(); - deleteAccelerationStructure(bottomLevelAS); - deleteAccelerationStructure(topLevelAS); - vertexBuffer.destroy(); - indexBuffer.destroy(); - transformBuffer.destroy(); - shaderBindingTables.raygen.destroy(); - shaderBindingTables.miss.destroy(); - shaderBindingTables.hit.destroy(); - ubo.destroy(); - texture.destroy(); - } - - void createAccelerationStructureBuffer(AccelerationStructure &accelerationStructure, VkAccelerationStructureBuildSizesInfoKHR buildSizeInfo) - { - VkBufferCreateInfo bufferCreateInfo{}; - bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferCreateInfo.size = buildSizeInfo.accelerationStructureSize; - bufferCreateInfo.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &accelerationStructure.buffer)); - VkMemoryRequirements memoryRequirements{}; - vkGetBufferMemoryRequirements(device, accelerationStructure.buffer, &memoryRequirements); - VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{}; - memoryAllocateFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; - memoryAllocateFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; - VkMemoryAllocateInfo memoryAllocateInfo{}; - memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memoryAllocateInfo.pNext = &memoryAllocateFlagsInfo; - memoryAllocateInfo.allocationSize = memoryRequirements.size; - memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &accelerationStructure.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, accelerationStructure.buffer, accelerationStructure.memory, 0)); - } - - /* - Create the bottom level acceleration structure contains the scene's actual geometry (vertices, triangles) - */ - void createBottomLevelAccelerationStructure() - { - // Setup vertices for a single triangle - struct Vertex { - float pos[3]; - float normal[3]; - float uv[2]; - }; - std::vector vertices = { - { { 0.5f, 0.5f, 0.0f }, {.0f, .0f, -1.0f}, { 1.0f, 1.0f} }, - { { -.5f, 0.5f, 0.0f }, {.0f, .0f, -1.0f}, { 0.0f, 1.0f} }, - { { -.5f, -.5f, 0.0f }, {.0f, .0f, -1.0f}, { 0.0f, 0.0f} }, - { { 0.5f, -.5f, 0.0f }, {.0f, .0f, -1.0f}, { 1.0f, 0.0f} }, - }; - - // Setup indices - std::vector indices = { 0, 1, 2, 0, 3, 2 }; - indexCount = static_cast(indices.size()); - - // Setup identity transform matrix - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f - }; - - // Create buffers - // For the sake of simplicity we won't stage the vertex data to the GPU memory - // Vertex buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &vertexBuffer, - vertices.size() * sizeof(Vertex), - vertices.data())); - // Index buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &indexBuffer, - indices.size() * sizeof(uint32_t), - indices.data())); - // Transform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &transformBuffer, - sizeof(VkTransformMatrixKHR), - &transformMatrix)); - - VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{}; - VkDeviceOrHostAddressConstKHR transformBufferDeviceAddress{}; - - vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(vertexBuffer.buffer); - indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(indexBuffer.buffer); - transformBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(transformBuffer.buffer); - - // Build - VkAccelerationStructureGeometryKHR accelerationStructureGeometry{}; - accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; - accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.maxVertex = 3; - accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(Vertex); - accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; - accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress; - accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0; - accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr; - accelerationStructureGeometry.geometry.triangles.transformData = transformBufferDeviceAddress; - - // Get size info - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{}; - accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - const uint32_t numTriangles = static_cast(indices.size() / 3); - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{}; - accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &numTriangles, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructureBuffer(bottomLevelAS, accelerationStructureBuildSizesInfo); - - VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{}; - accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - accelerationStructureCreateInfo.buffer = bottomLevelAS.buffer; - accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize; - accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &bottomLevelAS.handle); - - // Create a small scratch buffer used during build of the bottom level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{}; - accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = numTriangles; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{}; - accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; - accelerationDeviceAddressInfo.accelerationStructure = bottomLevelAS.handle; - bottomLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo); - - deleteScratchBuffer(scratchBuffer); - } - - /* - The top level acceleration structure contains the scene's object instances - */ - void createTopLevelAccelerationStructure() - { - VkTransformMatrixKHR transformMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f }; - - VkAccelerationStructureInstanceKHR instance{}; - instance.transform = transformMatrix; - instance.instanceCustomIndex = 0; - instance.mask = 0xFF; - instance.instanceShaderBindingTableRecordOffset = 0; - instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - instance.accelerationStructureReference = bottomLevelAS.deviceAddress; - - // Buffer for instance data - vks::Buffer instancesBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &instancesBuffer, - sizeof(VkAccelerationStructureInstanceKHR), - &instance)); - - VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{}; - instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer); - - VkAccelerationStructureGeometryKHR accelerationStructureGeometry{}; - accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE; - accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress; - - // Get size info - /* - The pSrcAccelerationStructure, dstAccelerationStructure, and mode members of pBuildInfo are ignored. Any VkDeviceOrHostAddressKHR members of pBuildInfo are ignored by this command, except that the hostAddress member of VkAccelerationStructureGeometryTrianglesDataKHR::transformData will be examined to check if it is NULL.* - */ - VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{}; - accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationStructureBuildGeometryInfo.geometryCount = 1; - accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - - uint32_t primitive_count = 1; - - VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{}; - accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; - vkGetAccelerationStructureBuildSizesKHR( - device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - &accelerationStructureBuildGeometryInfo, - &primitive_count, - &accelerationStructureBuildSizesInfo); - - createAccelerationStructureBuffer(topLevelAS, accelerationStructureBuildSizesInfo); - - VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{}; - accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - accelerationStructureCreateInfo.buffer = topLevelAS.buffer; - accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize; - accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &topLevelAS.handle); - - // Create a small scratch buffer used during build of the top level acceleration structure - ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize); - - VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{}; - accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle; - accelerationBuildGeometryInfo.geometryCount = 1; - accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry; - accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; - accelerationStructureBuildRangeInfo.primitiveCount = 1; - accelerationStructureBuildRangeInfo.primitiveOffset = 0; - accelerationStructureBuildRangeInfo.firstVertex = 0; - accelerationStructureBuildRangeInfo.transformOffset = 0; - std::vector accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo }; - - // Build the acceleration structure on the device via a one-time command buffer submission - // Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds - VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkCmdBuildAccelerationStructuresKHR( - commandBuffer, - 1, - &accelerationBuildGeometryInfo, - accelerationBuildStructureRangeInfos.data()); - vulkanDevice->flushCommandBuffer(commandBuffer, queue); - - VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{}; - accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; - accelerationDeviceAddressInfo.accelerationStructure = topLevelAS.handle; - topLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo); - - deleteScratchBuffer(scratchBuffer); - instancesBuffer.destroy(); - } - - /* - Create the Shader Binding Tables that binds the programs and top-level acceleration structure - - SBT Layout used in this sample: - - /-----------\ - | raygen | - |-----------| - | miss | - |-----------| - | hit | - \-----------/ - - */ - void createShaderBindingTables() { - const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize; - const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment); - const uint32_t groupCount = static_cast(shaderGroups.size()); - const uint32_t sbtSize = groupCount * handleSizeAligned; - - std::vector shaderHandleStorage(sbtSize); - VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data())); - - createShaderBindingTable(shaderBindingTables.raygen, 1); - createShaderBindingTable(shaderBindingTables.miss, 1); - createShaderBindingTable(shaderBindingTables.hit, 1); - - // Copy handles - memcpy(shaderBindingTables.raygen.mapped, shaderHandleStorage.data(), handleSize); - memcpy(shaderBindingTables.miss.mapped, shaderHandleStorage.data() + handleSizeAligned, handleSize); - memcpy(shaderBindingTables.hit.mapped, shaderHandleStorage.data() + handleSizeAligned * 2, handleSize); - } - - /* - Create the descriptor sets used for the ray tracing dispatch - */ - void createDescriptorSets() - { - std::vector poolSizes = { - { VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 }, - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 } - }; - VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool)); - - VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet)); - - VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks::initializers::writeDescriptorSetAccelerationStructureKHR(); - descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle; - - VkWriteDescriptorSet accelerationStructureWrite{}; - accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - // The specialized acceleration structure descriptor has to be chained - accelerationStructureWrite.pNext = &descriptorAccelerationStructureInfo; - accelerationStructureWrite.dstSet = descriptorSet; - accelerationStructureWrite.dstBinding = 0; - accelerationStructureWrite.descriptorCount = 1; - accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - - std::vector writeDescriptorSets = { - // Binding 0: Top level acceleration structure - accelerationStructureWrite, - // Binding 1: Ray tracing result image - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor), - // Binding 2: Uniform data - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor), - // Binding 3: Texture image - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &texture.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE); - } - - /* - Create our ray tracing pipeline - */ - void createRayTracingPipeline() - { - std::vector setLayoutBindings = { - // Binding 0: Top level acceleration structure - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0), - // Binding 1: Ray tracing result image - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_RAYGEN_BIT_KHR, 1), - // Binding 2: Uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR, 2), - // Binding 3: Texture image - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR, 3) - }; - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout)); - - // We pass buffer references for vertex and index buffers via push constants - VkPushConstantRange pushConstantRange{}; - pushConstantRange.stageFlags = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR; - pushConstantRange.offset = 0; - pushConstantRange.size = sizeof(uint64_t) * 2; - - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; - pipelineLayoutCI.pushConstantRangeCount = 1; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - /* - Setup ray tracing shader groups - */ - std::vector shaderStages; - - // Ray generation group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingtextures/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Miss group - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingtextures/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - shaderGroup.generalShader = static_cast(shaderStages.size()) - 1; - shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - shaderGroups.push_back(shaderGroup); - } - - // Closest hit group for doing texture lookups - { - shaderStages.push_back(loadShader(getShadersPath() + "raytracingtextures/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)); - VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; - shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; - shaderGroup.generalShader = VK_SHADER_UNUSED_KHR; - shaderGroup.closestHitShader = static_cast(shaderStages.size()) - 1; - shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; - // This group also uses an anyhit shader for doing transparency (see anyhit.rahit for details) - shaderStages.push_back(loadShader(getShadersPath() + "raytracingtextures/anyhit.rahit.spv", VK_SHADER_STAGE_ANY_HIT_BIT_KHR)); - shaderGroup.anyHitShader = static_cast(shaderStages.size()) - 1; - shaderGroups.push_back(shaderGroup); - } - - /* - Create the ray tracing pipeline - */ - VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI{}; - rayTracingPipelineCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; - rayTracingPipelineCI.stageCount = static_cast(shaderStages.size()); - rayTracingPipelineCI.pStages = shaderStages.data(); - rayTracingPipelineCI.groupCount = static_cast(shaderGroups.size()); - rayTracingPipelineCI.pGroups = shaderGroups.data(); - rayTracingPipelineCI.maxPipelineRayRecursionDepth = 1; - rayTracingPipelineCI.layout = pipelineLayout; - VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline)); - } - - /* - Create the uniform buffer used to pass matrices to the ray tracing ray generation shader - */ - void createUniformBuffer() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &ubo, - sizeof(uniformData), - &uniformData)); - VK_CHECK_RESULT(ubo.map()); - - updateUniformBuffers(); - } - - /* - If the window has been resized, we need to recreate the storage image and it's descriptor - */ - void handleResize() - { - // Recreate image - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - // Update descriptor - VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL }; - VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor); - vkUpdateDescriptorSets(device, 1, &resultImageWrite, 0, VK_NULL_HANDLE); - resized = false; - } - - /* - Command buffer generation - */ - void buildCommandBuffers() - { - if (resized) - { - handleResize(); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Dispatch the ray tracing commands - */ - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0); - - struct BufferReferences { - uint64_t vertices; - uint64_t indices; - } bufferReferences; - - bufferReferences.vertices = getBufferDeviceAddress(vertexBuffer.buffer); - bufferReferences.indices = getBufferDeviceAddress(indexBuffer.buffer); - - // We set the buffer references for the mesh to be rendered using a push constant - // If we wanted to render multiple objecets this would make it very easy to access their vertex and index buffers - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR, 0, sizeof(uint64_t) * 2, &bufferReferences); - - VkStridedDeviceAddressRegionKHR emptySbtEntry = {}; - vkCmdTraceRaysKHR( - drawCmdBuffers[i], - &shaderBindingTables.raygen.stridedDeviceAddressRegion, - &shaderBindingTables.miss.stridedDeviceAddressRegion, - &shaderBindingTables.hit.stridedDeviceAddressRegion, - &emptySbtEntry, - width, - height, - 1); - - /* - Copy ray tracing output to swap chain image - */ - - // Prepare current swap chain image as transfer destination - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Prepare ray tracing output image as transfer source - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresourceRange); - - VkImageCopy copyRegion{}; - copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.srcOffset = { 0, 0, 0 }; - copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - copyRegion.dstOffset = { 0, 0, 0 }; - copyRegion.extent = { width, height, 1 }; - vkCmdCopyImage(drawCmdBuffers[i], storageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChain.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); - - // Transition swap chain image back for presentation - vks::tools::setImageLayout( - drawCmdBuffers[i], - swapChain.images[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresourceRange); - - // Transition ray tracing output image back to general layout - vks::tools::setImageLayout( - drawCmdBuffers[i], - storageImage.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresourceRange); - - drawUI(drawCmdBuffers[i], frameBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void updateUniformBuffers() - { - uniformData.projInverse = glm::inverse(camera.matrices.perspective); - uniformData.viewInverse = glm::inverse(camera.matrices.view); - memcpy(ubo.mapped, &uniformData, sizeof(uniformData)); - } - - void getEnabledFeatures() - { - // Enable features required for ray tracing using feature chaining via pNext - enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; - enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE; - - enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR; - enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE; - enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures; - - enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE; - enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures; - - deviceCreatepNextChain = &enabledAccelerationStructureFeatures; - } - - void loadAssets() - { - texture.loadFromFile(getAssetPath() + "textures/gratefloor_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void prepare() - { - VulkanRaytracingSample::prepare(); - - loadAssets(); - - // Create the acceleration structures used to render the ray traced scene - createBottomLevelAccelerationStructure(); - createTopLevelAccelerationStructure(); - - createStorageImage(swapChain.colorFormat, { width, height, 1 }); - createUniformBuffer(); - createRayTracingPipeline(); - createShaderBindingTables(); - createDescriptorSets(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (camera.updated) - updateUniformBuffers(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/renderheadless/renderheadless.cpp b/examples/renderheadless/renderheadless.cpp deleted file mode 100644 index 59dbbac1..00000000 --- a/examples/renderheadless/renderheadless.cpp +++ /dev/null @@ -1,974 +0,0 @@ -/* -* Vulkan Example - Minimal headless rendering example -* -* Copyright (C) 2017-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#if defined(_WIN32) -#pragma comment(linker, "/subsystem:console") -#elif defined(VK_USE_PLATFORM_ANDROID_KHR) -#include -#include -#include -#include -#include "VulkanAndroid.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#define GLM_FORCE_RADIANS -#define GLM_FORCE_DEPTH_ZERO_TO_ONE -#include -#include - -#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) -#define VK_ENABLE_BETA_EXTENSIONS -#endif -#include -#include "VulkanTools.h" -#include "CommandLineParser.hpp" - -#if defined(VK_USE_PLATFORM_ANDROID_KHR) -android_app* androidapp; -#endif - -#define DEBUG (!NDEBUG) - -#define BUFFER_ELEMENTS 32 - -#if defined(VK_USE_PLATFORM_ANDROID_KHR) -#define LOG(...) ((void)__android_log_print(ANDROID_LOG_INFO, "vulkanExample", __VA_ARGS__)) -#else -#define LOG(...) printf(__VA_ARGS__) -#endif - -static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback( - VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, - uint64_t object, - size_t location, - int32_t messageCode, - const char* pLayerPrefix, - const char* pMessage, - void* pUserData) -{ - LOG("[VALIDATION]: %s - %s\n", pLayerPrefix, pMessage); - return VK_FALSE; -} - -CommandLineParser commandLineParser; - -class VulkanExample -{ -public: - VkInstance instance; - VkPhysicalDevice physicalDevice; - VkDevice device; - uint32_t queueFamilyIndex; - VkPipelineCache pipelineCache; - VkQueue queue; - VkCommandPool commandPool; - VkCommandBuffer commandBuffer; - VkDescriptorSetLayout descriptorSetLayout; - VkPipelineLayout pipelineLayout; - VkPipeline pipeline; - std::vector shaderModules; - VkBuffer vertexBuffer, indexBuffer; - VkDeviceMemory vertexMemory, indexMemory; - - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory memory; - VkImageView view; - }; - int32_t width, height; - VkFramebuffer framebuffer; - FrameBufferAttachment colorAttachment, depthAttachment; - VkRenderPass renderPass; - - VkDebugReportCallbackEXT debugReportCallback{}; - - std::string shaderDir = "glsl"; - - uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) { - VkPhysicalDeviceMemoryProperties deviceMemoryProperties; - vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties); - for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++) { - if ((typeBits & 1) == 1) { - if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { - return i; - } - } - typeBits >>= 1; - } - return 0; - } - - VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkBuffer *buffer, VkDeviceMemory *memory, VkDeviceSize size, void *data = nullptr) - { - // Create the buffer handle - VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(usageFlags, size); - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, buffer)); - - // Create the memory backing up the buffer handle - VkMemoryRequirements memReqs; - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - vkGetBufferMemoryRequirements(device, *buffer, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, memoryPropertyFlags); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, memory)); - - if (data != nullptr) { - void *mapped; - VK_CHECK_RESULT(vkMapMemory(device, *memory, 0, size, 0, &mapped)); - memcpy(mapped, data, size); - vkUnmapMemory(device, *memory); - } - - VK_CHECK_RESULT(vkBindBufferMemory(device, *buffer, *memory, 0)); - - return VK_SUCCESS; - } - - /* - Submit command buffer to a queue and wait for fence until queue operations have been finished - */ - void submitWork(VkCommandBuffer cmdBuffer, VkQueue queue) - { - VkSubmitInfo submitInfo = vks::initializers::submitInfo(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &cmdBuffer; - VkFenceCreateInfo fenceInfo = vks::initializers::fenceCreateInfo(); - VkFence fence; - VK_CHECK_RESULT(vkCreateFence(device, &fenceInfo, nullptr, &fence)); - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence)); - VK_CHECK_RESULT(vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX)); - vkDestroyFence(device, fence, nullptr); - } - - VulkanExample() - { - LOG("Running headless rendering example\n"); - -#if defined(VK_USE_PLATFORM_ANDROID_KHR) - LOG("loading vulkan lib"); - vks::android::loadVulkanLibrary(); -#endif - - if (commandLineParser.isSet("shaders")) { - shaderDir = commandLineParser.getValueAsString("shaders", "glsl"); - } - - VkApplicationInfo appInfo = {}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "Vulkan headless example"; - appInfo.pEngineName = "VulkanExample"; - appInfo.apiVersion = VK_API_VERSION_1_0; - // Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions - if (shaderDir == "slang") { - appInfo.apiVersion = VK_API_VERSION_1_1; - } - - /* - Vulkan instance creation (without surface extensions) - */ - VkInstanceCreateInfo instanceCreateInfo = {}; - instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - instanceCreateInfo.pApplicationInfo = &appInfo; - - uint32_t layerCount = 1; - const char* validationLayers[] = { "VK_LAYER_KHRONOS_validation" }; - - std::vector instanceExtensions = {}; -#if DEBUG - // Check if layers are available - uint32_t instanceLayerCount; - vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr); - std::vector instanceLayers(instanceLayerCount); - vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayers.data()); - - bool layersAvailable = true; - for (auto layerName : validationLayers) { - bool layerAvailable = false; - for (auto& instanceLayer : instanceLayers) { - if (strcmp(instanceLayer.layerName, layerName) == 0) { - layerAvailable = true; - break; - } - } - if (!layerAvailable) { - layersAvailable = false; - break; - } - } - - if (layersAvailable) { - instanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); - instanceCreateInfo.ppEnabledLayerNames = validationLayers; - instanceCreateInfo.enabledLayerCount = layerCount; - } -#endif -#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) - // SRS - When running on macOS with MoltenVK, enable VK_KHR_get_physical_device_properties2 (required by VK_KHR_portability_subset) - instanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); -#if defined(VK_KHR_portability_enumeration) - // SRS - When running on macOS with MoltenVK and VK_KHR_portability_enumeration is defined and supported by the instance, enable the extension and the flag - uint32_t instanceExtCount = 0; - vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, nullptr); - if (instanceExtCount > 0) - { - std::vector extensions(instanceExtCount); - if (vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, &extensions.front()) == VK_SUCCESS) - { - for (VkExtensionProperties extension : extensions) - { - if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) - { - instanceExtensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); - instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; - break; - } - } - } - } -#endif -#endif - instanceCreateInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size(); - instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data(); - VK_CHECK_RESULT(vkCreateInstance(&instanceCreateInfo, nullptr, &instance)); - -#if defined(VK_USE_PLATFORM_ANDROID_KHR) - vks::android::loadVulkanFunctions(instance); -#endif -#if DEBUG - if (layersAvailable) { - VkDebugReportCallbackCreateInfoEXT debugReportCreateInfo = {}; - debugReportCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; - debugReportCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; - debugReportCreateInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)debugMessageCallback; - - // We have to explicitly load this function. - PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT")); - assert(vkCreateDebugReportCallbackEXT); - VK_CHECK_RESULT(vkCreateDebugReportCallbackEXT(instance, &debugReportCreateInfo, nullptr, &debugReportCallback)); - } -#endif - - /* - Vulkan device creation - */ - uint32_t deviceCount = 0; - VK_CHECK_RESULT(vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr)); - std::vector physicalDevices(deviceCount); - VK_CHECK_RESULT(vkEnumeratePhysicalDevices(instance, &deviceCount, physicalDevices.data())); - physicalDevice = physicalDevices[0]; - - VkPhysicalDeviceProperties deviceProperties; - vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); - LOG("GPU: %s\n", deviceProperties.deviceName); - - // Request a single graphics queue - const float defaultQueuePriority(0.0f); - VkDeviceQueueCreateInfo queueCreateInfo = {}; - uint32_t queueFamilyCount; - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr); - std::vector queueFamilyProperties(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilyProperties.data()); - for (uint32_t i = 0; i < static_cast(queueFamilyProperties.size()); i++) { - if (queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { - queueFamilyIndex = i; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = i; - queueCreateInfo.queueCount = 1; - queueCreateInfo.pQueuePriorities = &defaultQueuePriority; - break; - } - } - // Create logical device - VkDeviceCreateInfo deviceCreateInfo = {}; - deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - deviceCreateInfo.queueCreateInfoCount = 1; - deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; - std::vector deviceExtensions = {}; - - // Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions - if (shaderDir == "slang") { - deviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); - deviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); - } - -#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_KHR_portability_subset) - // When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension - uint32_t deviceExtCount = 0; - vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, nullptr); - if (deviceExtCount > 0) - { - std::vector extensions(deviceExtCount); - if (vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, &extensions.front()) == VK_SUCCESS) - { - for (VkExtensionProperties extension : extensions) - { - if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) - { - deviceExtensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); - break; - } - } - } - } -#endif - deviceCreateInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size(); - deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data(); - VK_CHECK_RESULT(vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device)); - - // Get a graphics queue - vkGetDeviceQueue(device, queueFamilyIndex, 0, &queue); - - // Command pool - VkCommandPoolCreateInfo cmdPoolInfo = {}; - cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmdPoolInfo.queueFamilyIndex = queueFamilyIndex; - cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &commandPool)); - - /* - Prepare vertex and index buffers - */ - struct Vertex { - float position[3]; - float color[3]; - }; - { - std::vector vertices = { - { { 1.0f, 1.0f, 0.0f }, { 1.0f, 0.0f, 0.0f } }, - { { -1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } }, - { { 0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } } - }; - std::vector indices = { 0, 1, 2 }; - - const VkDeviceSize vertexBufferSize = vertices.size() * sizeof(Vertex); - const VkDeviceSize indexBufferSize = indices.size() * sizeof(uint32_t); - - VkBuffer stagingBuffer; - VkDeviceMemory stagingMemory; - - // Command buffer for copy commands (reused) - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - VkCommandBuffer copyCmd; - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, ©Cmd)); - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - // Copy input data to VRAM using a staging buffer - { - // Vertices - createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - &stagingMemory, - vertexBufferSize, - vertices.data()); - - createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &vertexBuffer, - &vertexMemory, - vertexBufferSize); - - VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo)); - VkBufferCopy copyRegion = {}; - copyRegion.size = vertexBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffer, vertexBuffer, 1, ©Region); - VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd)); - - submitWork(copyCmd, queue); - - vkDestroyBuffer(device, stagingBuffer, nullptr); - vkFreeMemory(device, stagingMemory, nullptr); - - // Indices - createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, - &stagingMemory, - indexBufferSize, - indices.data()); - - createBuffer( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &indexBuffer, - &indexMemory, - indexBufferSize); - - VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo)); - copyRegion.size = indexBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffer, indexBuffer, 1, ©Region); - VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd)); - - submitWork(copyCmd, queue); - - vkDestroyBuffer(device, stagingBuffer, nullptr); - vkFreeMemory(device, stagingMemory, nullptr); - } - } - - /* - Create framebuffer attachments - */ - width = 1024; - height = 1024; - VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; - VkFormat depthFormat; - vks::tools::getSupportedDepthFormat(physicalDevice, &depthFormat); - { - // Color attachment - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = colorFormat; - image.extent.width = width; - image.extent.height = height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &colorAttachment.image)); - vkGetImageMemoryRequirements(device, colorAttachment.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &colorAttachment.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, colorAttachment.image, colorAttachment.memory, 0)); - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = colorFormat; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = colorAttachment.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &colorAttachment.view)); - - // Depth stencil attachment - image.format = depthFormat; - image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &depthAttachment.image)); - vkGetImageMemoryRequirements(device, depthAttachment.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depthAttachment.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, depthAttachment.image, depthAttachment.memory, 0)); - - VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo(); - depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilView.format = depthFormat; - depthStencilView.flags = 0; - depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (depthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) - depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - depthStencilView.subresourceRange.baseMipLevel = 0; - depthStencilView.subresourceRange.levelCount = 1; - depthStencilView.subresourceRange.baseArrayLayer = 0; - depthStencilView.subresourceRange.layerCount = 1; - depthStencilView.image = depthAttachment.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthAttachment.view)); - } - - /* - Create renderpass - */ - { - std::array attchmentDescriptions = {}; - // Color attachment - attchmentDescriptions[0].format = colorFormat; - attchmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attchmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - // Depth attachment - attchmentDescriptions[1].format = depthFormat; - attchmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT; - attchmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attchmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attchmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attchmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attchmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - VkAttachmentReference depthReference = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - subpassDescription.pDepthStencilAttachment = &depthReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Create the actual renderpass - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attchmentDescriptions.size()); - renderPassInfo.pAttachments = attchmentDescriptions.data(); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpassDescription; - renderPassInfo.dependencyCount = static_cast(dependencies.size()); - renderPassInfo.pDependencies = dependencies.data(); - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass)); - - VkImageView attachments[2]; - attachments[0] = colorAttachment.view; - attachments[1] = depthAttachment.view; - - VkFramebufferCreateInfo framebufferCreateInfo = vks::initializers::framebufferCreateInfo(); - framebufferCreateInfo.renderPass = renderPass; - framebufferCreateInfo.attachmentCount = 2; - framebufferCreateInfo.pAttachments = attachments; - framebufferCreateInfo.width = width; - framebufferCreateInfo.height = height; - framebufferCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &framebufferCreateInfo, nullptr, &framebuffer)); - } - - /* - Prepare graphics pipeline - */ - { - std::vector setLayoutBindings = {}; - VkDescriptorSetLayoutCreateInfo descriptorLayout = - vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = - vks::initializers::pipelineLayoutCreateInfo(nullptr, 0); - - // MVP via push constant block - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {}; - pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - VK_CHECK_RESULT(vkCreatePipelineCache(device, &pipelineCacheCreateInfo, nullptr, &pipelineCache)); - - // Create pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = - vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - - VkPipelineRasterizationStateCreateInfo rasterizationState = - vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE); - - VkPipelineColorBlendAttachmentState blendAttachmentState = - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - - VkPipelineColorBlendStateCreateInfo colorBlendState = - vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - - VkPipelineDepthStencilStateCreateInfo depthStencilState = - vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - - VkPipelineViewportStateCreateInfo viewportState = - vks::initializers::pipelineViewportStateCreateInfo(1, 1); - - VkPipelineMultisampleStateCreateInfo multisampleState = - vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - - std::vector dynamicStateEnables = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR - }; - VkPipelineDynamicStateCreateInfo dynamicState = - vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = - vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - - std::array shaderStages{}; - - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - - // Vertex bindings an attributes - // Binding description - std::vector vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - }; - - // Attribute descriptions - std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Color - }; - - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - pipelineCreateInfo.pVertexInputState = &vertexInputState; - - if (commandLineParser.isSet("shaders")) { - shaderDir = commandLineParser.getValueAsString("shaders", "glsl"); - } - const std::string shadersPath = getShaderBasePath() + shaderDir + "/renderheadless/"; - - shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shaderStages[0].pName = "main"; - shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderStages[1].pName = "main"; -#if defined(VK_USE_PLATFORM_ANDROID_KHR) - shaderStages[0].module = vks::tools::loadShader(androidapp->activity->assetManager, (shadersPath + "triangle.vert.spv").c_str(), device); - shaderStages[1].module = vks::tools::loadShader(androidapp->activity->assetManager, (shadersPath + "triangle.frag.spv").c_str(), device); -#else - shaderStages[0].module = vks::tools::loadShader((shadersPath + "triangle.vert.spv").c_str(), device); - shaderStages[1].module = vks::tools::loadShader((shadersPath + "triangle.frag.spv").c_str(), device); -#endif - shaderModules = { shaderStages[0].module, shaderStages[1].module }; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); - } - - /* - Command buffer creation - */ - { - VkCommandBuffer commandBuffer; - VkCommandBufferAllocateInfo cmdBufAllocateInfo = - vks::initializers::commandBufferAllocateInfo(commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &commandBuffer)); - - VkCommandBufferBeginInfo cmdBufInfo = - vks::initializers::commandBufferBeginInfo(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &cmdBufInfo)); - - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = {}; - renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = framebuffer; - - vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = {}; - viewport.height = (float)height; - viewport.width = (float)width; - viewport.minDepth = (float)0.0f; - viewport.maxDepth = (float)1.0f; - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - - // Update dynamic scissor state - VkRect2D scissor = {}; - scissor.extent.width = width; - scissor.extent.height = height; - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - // Render scene - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer, offsets); - vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT32); - - std::vector pos = { - glm::vec3(-1.5f, 0.0f, -4.0f), - glm::vec3( 0.0f, 0.0f, -2.5f), - glm::vec3( 1.5f, 0.0f, -4.0f), - }; - - for (auto v : pos) { - glm::mat4 mvpMatrix = glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.1f, 256.0f) * glm::translate(glm::mat4(1.0f), v); - vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(mvpMatrix), &mvpMatrix); - vkCmdDrawIndexed(commandBuffer, 3, 1, 0, 0, 0); - } - - vkCmdEndRenderPass(commandBuffer); - - VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer)); - - submitWork(commandBuffer, queue); - - vkDeviceWaitIdle(device); - } - - /* - Copy framebuffer image to host visible image - */ - const char* imagedata; - { - // Create the linear tiled destination image to copy to and to read the memory from - VkImageCreateInfo imgCreateInfo(vks::initializers::imageCreateInfo()); - imgCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imgCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; - imgCreateInfo.extent.width = width; - imgCreateInfo.extent.height = height; - imgCreateInfo.extent.depth = 1; - imgCreateInfo.arrayLayers = 1; - imgCreateInfo.mipLevels = 1; - imgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imgCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; - imgCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - // Create the image - VkImage dstImage; - VK_CHECK_RESULT(vkCreateImage(device, &imgCreateInfo, nullptr, &dstImage)); - // Create memory to back up the image - VkMemoryRequirements memRequirements; - VkMemoryAllocateInfo memAllocInfo(vks::initializers::memoryAllocateInfo()); - VkDeviceMemory dstImageMemory; - vkGetImageMemoryRequirements(device, dstImage, &memRequirements); - memAllocInfo.allocationSize = memRequirements.size; - // Memory must be host visible to copy from - memAllocInfo.memoryTypeIndex = getMemoryTypeIndex(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &dstImageMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, dstImage, dstImageMemory, 0)); - - // Do the actual blit from the offscreen image to our host visible destination image - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - VkCommandBuffer copyCmd; - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, ©Cmd)); - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo)); - - // Transition destination image to transfer destination layout - vks::tools::insertImageMemoryBarrier( - copyCmd, - dstImage, - 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - - // colorAttachment.image is already in VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, and does not need to be transitioned - - VkImageCopy imageCopyRegion{}; - imageCopyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageCopyRegion.srcSubresource.layerCount = 1; - imageCopyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageCopyRegion.dstSubresource.layerCount = 1; - imageCopyRegion.extent.width = width; - imageCopyRegion.extent.height = height; - imageCopyRegion.extent.depth = 1; - - vkCmdCopyImage( - copyCmd, - colorAttachment.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &imageCopyRegion); - - // Transition destination image to general layout, which is the required layout for mapping the image memory later on - vks::tools::insertImageMemoryBarrier( - copyCmd, - dstImage, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_MEMORY_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - - VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd)); - - submitWork(copyCmd, queue); - - // Get layout of the image (including row pitch) - VkImageSubresource subResource{}; - subResource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - VkSubresourceLayout subResourceLayout; - - vkGetImageSubresourceLayout(device, dstImage, &subResource, &subResourceLayout); - - // Map image memory so we can start copying from it - vkMapMemory(device, dstImageMemory, 0, VK_WHOLE_SIZE, 0, (void**)&imagedata); - imagedata += subResourceLayout.offset; - - /* - Save host visible framebuffer image to disk (ppm format) - */ - -#if defined (VK_USE_PLATFORM_ANDROID_KHR) - const char* filename = strcat(getenv("EXTERNAL_STORAGE"), "/headless.ppm"); -#else - const char* filename = "headless.ppm"; -#endif - std::ofstream file(filename, std::ios::out | std::ios::binary); - - // ppm header - file << "P6\n" << width << "\n" << height << "\n" << 255 << "\n"; - - // If source is BGR (destination is always RGB) and we can't use blit (which does automatic conversion), we'll have to manually swizzle color components - // Check if source is BGR and needs swizzle - std::vector formatsBGR = { VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_SNORM }; - const bool colorSwizzle = (std::find(formatsBGR.begin(), formatsBGR.end(), VK_FORMAT_R8G8B8A8_UNORM) != formatsBGR.end()); - - // ppm binary pixel data - for (int32_t y = 0; y < height; y++) { - unsigned int *row = (unsigned int*)imagedata; - for (int32_t x = 0; x < width; x++) { - if (colorSwizzle) { - file.write((char*)row + 2, 1); - file.write((char*)row + 1, 1); - file.write((char*)row, 1); - } - else { - file.write((char*)row, 3); - } - row++; - } - imagedata += subResourceLayout.rowPitch; - } - file.close(); - - LOG("Framebuffer image saved to %s\n", filename); - - // Clean up resources - vkUnmapMemory(device, dstImageMemory); - vkFreeMemory(device, dstImageMemory, nullptr); - vkDestroyImage(device, dstImage, nullptr); - } - - vkQueueWaitIdle(queue); - } - - ~VulkanExample() - { - vkDestroyBuffer(device, vertexBuffer, nullptr); - vkFreeMemory(device, vertexMemory, nullptr); - vkDestroyBuffer(device, indexBuffer, nullptr); - vkFreeMemory(device, indexMemory, nullptr); - vkDestroyImageView(device, colorAttachment.view, nullptr); - vkDestroyImage(device, colorAttachment.image, nullptr); - vkFreeMemory(device, colorAttachment.memory, nullptr); - vkDestroyImageView(device, depthAttachment.view, nullptr); - vkDestroyImage(device, depthAttachment.image, nullptr); - vkFreeMemory(device, depthAttachment.memory, nullptr); - vkDestroyRenderPass(device, renderPass, nullptr); - vkDestroyFramebuffer(device, framebuffer, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineCache(device, pipelineCache, nullptr); - vkDestroyCommandPool(device, commandPool, nullptr); - for (auto shadermodule : shaderModules) { - vkDestroyShaderModule(device, shadermodule, nullptr); - } - vkDestroyDevice(device, nullptr); -#if DEBUG - if (debugReportCallback) { - PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallback = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT")); - assert(vkDestroyDebugReportCallback); - vkDestroyDebugReportCallback(instance, debugReportCallback, nullptr); - } -#endif - vkDestroyInstance(instance, nullptr); -#if defined(VK_USE_PLATFORM_ANDROID_KHR) - vks::android::freeVulkanLibrary(); -#endif - } -}; - -#if defined(VK_USE_PLATFORM_ANDROID_KHR) -void handleAppCommand(android_app * app, int32_t cmd) { - if (cmd == APP_CMD_INIT_WINDOW) { - VulkanExample *vulkanExample = new VulkanExample(); - delete(vulkanExample); - ANativeActivity_finish(app->activity); - } -} -void android_main(android_app* state) { - androidapp = state; - androidapp->onAppCmd = handleAppCommand; - int ident, events; - struct android_poll_source* source; - while ((ident = ALooper_pollOnce(-1, NULL, &events, (void**)&source)) > ALOOPER_POLL_TIMEOUT) { - if (source != NULL) { - source->process(androidapp, source); - } - if (androidapp->destroyRequested != 0) { - break; - } - } -} -#else -int main(int argc, char* argv[]) { - commandLineParser.add("help", { "--help" }, 0, "Show help"); - commandLineParser.add("shaders", { "-s", "--shaders" }, 1, "Select shader type to use (glsl, hlsl or slang)"); - commandLineParser.parse(argc, argv); - if (commandLineParser.isSet("help")) { - commandLineParser.printHelp(); - std::cin.get(); - return 0; - } - VulkanExample *vulkanExample = new VulkanExample(); - std::cout << "Finished. Press enter to terminate..."; - std::cin.get(); - delete(vulkanExample); - return 0; -} -#endif diff --git a/examples/screenshot/screenshot.cpp b/examples/screenshot/screenshot.cpp deleted file mode 100644 index 3e2a48c7..00000000 --- a/examples/screenshot/screenshot.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/* -* Vulkan Example - Taking screenshots -* -* This sample shows how to get the conents of the swapchain (render output) and store them to disk (see saveScreenshot) -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - vkglTF::Model model; - - struct UniformData { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - int32_t texIndex = 0; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - bool screenshotSaved{ false }; - - VulkanExample() : VulkanExampleBase() - { - title = "Saving framebuffer to screenshot"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(-25.0f, 23.75f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -3.0f)); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - void loadAssets() - { - model.loadFromFile(getAssetPath() + "models/chinesedragon.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - model.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), // Binding 0: Vertex shader uniform buffer - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), // Binding 0: Vertex shader uniform buffer - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - std::array shaderStages = { - loadShader(getShadersPath() + "screenshot/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getShadersPath() + "screenshot/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT), - }; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData)); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.model = glm::mat4(1.0f); - uniformBuffer.copyTo(&uniformData, sizeof(UniformData)); - } - - // Take a screenshot from the current swapchain image - // This is done using a blit from the swapchain image to a linear image whose memory content is then saved as a ppm image - // Getting the image date directly from a swapchain image wouldn't work as they're usually stored in an implementation dependent optimal tiling format - // Note: This requires the swapchain images to be created with the VK_IMAGE_USAGE_TRANSFER_SRC_BIT flag (see VulkanSwapChain::create) - void saveScreenshot(const char *filename) - { - screenshotSaved = false; - bool supportsBlit = true; - - // Check blit support for source and destination - VkFormatProperties formatProps; - - // Check if the device supports blitting from optimal images (the swapchain images are in optimal format) - vkGetPhysicalDeviceFormatProperties(physicalDevice, swapChain.colorFormat, &formatProps); - if (!(formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) { - std::cerr << "Device does not support blitting from optimal tiled images, using copy instead of blit!" << std::endl; - supportsBlit = false; - } - - // Check if the device supports blitting to linear images - vkGetPhysicalDeviceFormatProperties(physicalDevice, VK_FORMAT_R8G8B8A8_UNORM, &formatProps); - if (!(formatProps.linearTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) { - std::cerr << "Device does not support blitting to linear tiled images, using copy instead of blit!" << std::endl; - supportsBlit = false; - } - - // Source for the copy is the last rendered swapchain image - VkImage srcImage = swapChain.images[currentBuffer]; - - // Create the linear tiled destination image to copy to and to read the memory from - VkImageCreateInfo imageCreateCI(vks::initializers::imageCreateInfo()); - imageCreateCI.imageType = VK_IMAGE_TYPE_2D; - // Note that vkCmdBlitImage (if supported) will also do format conversions if the swapchain color format would differ - imageCreateCI.format = VK_FORMAT_R8G8B8A8_UNORM; - imageCreateCI.extent.width = width; - imageCreateCI.extent.height = height; - imageCreateCI.extent.depth = 1; - imageCreateCI.arrayLayers = 1; - imageCreateCI.mipLevels = 1; - imageCreateCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateCI.tiling = VK_IMAGE_TILING_LINEAR; - imageCreateCI.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; - // Create the image - VkImage dstImage; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateCI, nullptr, &dstImage)); - // Create memory to back up the image - VkMemoryRequirements memRequirements; - VkMemoryAllocateInfo memAllocInfo(vks::initializers::memoryAllocateInfo()); - VkDeviceMemory dstImageMemory; - vkGetImageMemoryRequirements(device, dstImage, &memRequirements); - memAllocInfo.allocationSize = memRequirements.size; - // Memory must be host visible to copy from - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &dstImageMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, dstImage, dstImageMemory, 0)); - - // Do the actual blit from the swapchain image to our host visible destination image - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // Transition destination image to transfer destination layout - vks::tools::insertImageMemoryBarrier( - copyCmd, - dstImage, - 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - - // Transition swapchain image from present to transfer source layout - vks::tools::insertImageMemoryBarrier( - copyCmd, - srcImage, - VK_ACCESS_MEMORY_READ_BIT, - VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - - // If source and destination support blit we'll blit as this also does automatic format conversion (e.g. from BGR to RGB) - if (supportsBlit) - { - // Define the region to blit (we will blit the whole swapchain image) - VkOffset3D blitSize; - blitSize.x = width; - blitSize.y = height; - blitSize.z = 1; - VkImageBlit imageBlitRegion{}; - imageBlitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageBlitRegion.srcSubresource.layerCount = 1; - imageBlitRegion.srcOffsets[1] = blitSize; - imageBlitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageBlitRegion.dstSubresource.layerCount = 1; - imageBlitRegion.dstOffsets[1] = blitSize; - - // Issue the blit command - vkCmdBlitImage( - copyCmd, - srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &imageBlitRegion, - VK_FILTER_NEAREST); - } - else - { - // Otherwise use image copy (requires us to manually flip components) - VkImageCopy imageCopyRegion{}; - imageCopyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageCopyRegion.srcSubresource.layerCount = 1; - imageCopyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageCopyRegion.dstSubresource.layerCount = 1; - imageCopyRegion.extent.width = width; - imageCopyRegion.extent.height = height; - imageCopyRegion.extent.depth = 1; - - // Issue the copy command - vkCmdCopyImage( - copyCmd, - srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &imageCopyRegion); - } - - // Transition destination image to general layout, which is the required layout for mapping the image memory later on - vks::tools::insertImageMemoryBarrier( - copyCmd, - dstImage, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_MEMORY_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - - // Transition back the swap chain image after the blit is done - vks::tools::insertImageMemoryBarrier( - copyCmd, - srcImage, - VK_ACCESS_TRANSFER_READ_BIT, - VK_ACCESS_MEMORY_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - - vulkanDevice->flushCommandBuffer(copyCmd, queue); - - // Get layout of the image (including row pitch) - VkImageSubresource subResource { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 }; - VkSubresourceLayout subResourceLayout; - vkGetImageSubresourceLayout(device, dstImage, &subResource, &subResourceLayout); - - // Map image memory so we can start copying from it - const char* data; - vkMapMemory(device, dstImageMemory, 0, VK_WHOLE_SIZE, 0, (void**)&data); - data += subResourceLayout.offset; - - std::ofstream file(filename, std::ios::out | std::ios::binary); - - // ppm header - file << "P6\n" << width << "\n" << height << "\n" << 255 << "\n"; - - // If source is BGR (destination is always RGB) and we can't use blit (which does automatic conversion), we'll have to manually swizzle color components - bool colorSwizzle = false; - // Check if source is BGR - // Note: Not complete, only contains most common and basic BGR surface formats for demonstration purposes - if (!supportsBlit) - { - std::vector formatsBGR = { VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_SNORM }; - colorSwizzle = (std::find(formatsBGR.begin(), formatsBGR.end(), swapChain.colorFormat) != formatsBGR.end()); - } - - // ppm binary pixel data - for (uint32_t y = 0; y < height; y++) - { - unsigned int *row = (unsigned int*)data; - for (uint32_t x = 0; x < width; x++) - { - if (colorSwizzle) - { - file.write((char*)row+2, 1); - file.write((char*)row+1, 1); - file.write((char*)row, 1); - } - else - { - file.write((char*)row, 3); - } - row++; - } - data += subResourceLayout.rowPitch; - } - file.close(); - - std::cout << "Screenshot saved to disk" << std::endl; - - // Clean up resources - vkUnmapMemory(device, dstImageMemory); - vkFreeMemory(device, dstImageMemory, nullptr); - vkDestroyImage(device, dstImage, nullptr); - - screenshotSaved = true; - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Functions")) { - if (overlay->button("Take screenshot")) { - saveScreenshot("screenshot.ppm"); - } - if (screenshotSaved) { - overlay->text("Screenshot saved as screenshot.ppm"); - } - } - } - -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/shaderobjects/shaderobjects.cpp b/examples/shaderobjects/shaderobjects.cpp deleted file mode 100644 index 3ba4e49e..00000000 --- a/examples/shaderobjects/shaderobjects.cpp +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Vulkan Example - Using shader objects via VK_EXT_shader_object - * - * Copyright (C) 2023 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample: public VulkanExampleBase -{ -public: - vkglTF::Model scene; - - // Same uniform buffer layout as shader - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 lightPos = glm::vec4(0.0f, 2.0f, 1.0f, 0.0f); - } uniformData; - vks::Buffer uniformBuffer; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VkShaderEXT shaders[2]; - - VkPhysicalDeviceShaderObjectFeaturesEXT enabledShaderObjectFeaturesEXT{}; - VkPhysicalDeviceDynamicRenderingFeaturesKHR enabledDynamicRenderingFeaturesKHR{}; - - PFN_vkCreateShadersEXT vkCreateShadersEXT{ VK_NULL_HANDLE }; - PFN_vkDestroyShaderEXT vkDestroyShaderEXT{ VK_NULL_HANDLE }; - PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT{ VK_NULL_HANDLE }; - PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT{ VK_NULL_HANDLE }; - - // VK_EXT_shader_objects requires render passes to be dynamic - PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR{ VK_NULL_HANDLE }; - PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR{ VK_NULL_HANDLE }; - - // With VK_EXT_shader_object pipeline state must be set at command buffer creation using these functions - PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT{ VK_NULL_HANDLE }; - PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT{ VK_NULL_HANDLE }; - - // VK_EXT_vertex_input_dynamic_state - PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Shader objects (VK_EXT_shader_object)"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -10.5f)); - camera.setRotation(glm::vec3(-25.0f, 15.0f, 0.0f)); - camera.setRotationSpeed(0.5f); - camera.setPerspective(60.0f, (float)(width) / (float)height, 0.1f, 256.0f); - - enabledDeviceExtensions.push_back(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); - - enabledDeviceExtensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); - - // With VK_EXT_shader_object all baked pipeline state is set dynamically at command buffer creation, so we need to enable additional extensions - enabledDeviceExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); - - // Since we are not requiring Vulkan 1.2, we need to enable some additional extensios for dynamic rendering - enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME); - - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - - enabledShaderObjectFeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT; - enabledShaderObjectFeaturesEXT.shaderObject = VK_TRUE; - - enabledDynamicRenderingFeaturesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR; - enabledDynamicRenderingFeaturesKHR.dynamicRendering = VK_TRUE; - enabledDynamicRenderingFeaturesKHR.pNext = &enabledShaderObjectFeaturesEXT; - - deviceCreatepNextChain = &enabledDynamicRenderingFeaturesKHR; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - vkDestroyShaderEXT(device, shaders[0], nullptr); - vkDestroyShaderEXT(device, shaders[1], nullptr); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - scene.loadFromFile(getAssetPath() + "models/treasure_smooth.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - // Sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - // Loads a binary shader file - void _loadShader(std::string filename, char* &code, size_t &size) { - // @todo: Android - std::ifstream is(filename, std::ios::binary | std::ios::in | std::ios::ate); - if (is.is_open()) - { - size = is.tellg(); - is.seekg(0, std::ios::beg); - code = new char[size]; - is.read(code, size); - is.close(); - assert(size > 0); - } - else - { - vks::tools::exitFatal("Error: Could not open shader " + filename, VK_ERROR_UNKNOWN); - } - } - - void createShaderObjects() - { - size_t shaderCodeSizes[2]{}; - char* shaderCodes[2]{}; - - VkShaderCreateInfoEXT shaderCreateInfos[2]{}; - - // With VK_EXT_shader_object we can generate an implementation dependent binary file that's faster to load - // So we check if the binray files exist and if we can load it instead of the SPIR-V - bool binaryShadersLoaded = false; - - if (vks::tools::fileExists(getShadersPath() + "shaderobjects/phong.vert.bin") && vks::tools::fileExists(getShadersPath() + "shaderobjects/phong.frag.bin")) { - // VS - _loadShader(getShadersPath() + "shaderobjects/phong.vert.bin", shaderCodes[0], shaderCodeSizes[0]); - shaderCreateInfos[0].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT; - shaderCreateInfos[0].flags = VK_SHADER_CREATE_LINK_STAGE_BIT_EXT; - shaderCreateInfos[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shaderCreateInfos[0].nextStage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderCreateInfos[0].codeType = VK_SHADER_CODE_TYPE_BINARY_EXT; - shaderCreateInfos[0].pCode = shaderCodes[0]; - shaderCreateInfos[0].codeSize = shaderCodeSizes[0]; - shaderCreateInfos[0].pName = "main"; - shaderCreateInfos[0].setLayoutCount = 1; - shaderCreateInfos[0].pSetLayouts = &descriptorSetLayout; - - // FS - _loadShader(getShadersPath() + "shaderobjects/phong.frag.bin", shaderCodes[1], shaderCodeSizes[1]); - shaderCreateInfos[1].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT; - shaderCreateInfos[1].flags = VK_SHADER_CREATE_LINK_STAGE_BIT_EXT; - shaderCreateInfos[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderCreateInfos[1].nextStage = 0; - shaderCreateInfos[1].codeType = VK_SHADER_CODE_TYPE_BINARY_EXT; - shaderCreateInfos[1].pCode = shaderCodes[1]; - shaderCreateInfos[1].codeSize = shaderCodeSizes[1]; - shaderCreateInfos[1].pName = "main"; - shaderCreateInfos[1].setLayoutCount = 1; - shaderCreateInfos[1].pSetLayouts = &descriptorSetLayout; - - VkResult result = vkCreateShadersEXT(device, 2, shaderCreateInfos, nullptr, shaders); - // If the function returns e.g. VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT, the binary file is no longer (or not at all) compatible with the current implementation - if (result == VK_SUCCESS) { - binaryShadersLoaded = true; - } else { - std::cout << "Could not load binary shader files (" << vks::tools::errorString(result) << ", loading SPIR - V instead\n"; - } - } - - // If the binary files weren't present, or we could not load them, we load from SPIR-V - if (!binaryShadersLoaded) { - // VS - _loadShader(getShadersPath() + "shaderobjects/phong.vert.spv", shaderCodes[0], shaderCodeSizes[0]); - shaderCreateInfos[0].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT; - shaderCreateInfos[0].flags = VK_SHADER_CREATE_LINK_STAGE_BIT_EXT; - shaderCreateInfos[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shaderCreateInfos[0].nextStage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderCreateInfos[0].codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT; - shaderCreateInfos[0].pCode = shaderCodes[0]; - shaderCreateInfos[0].codeSize = shaderCodeSizes[0]; - shaderCreateInfos[0].pName = "main"; - shaderCreateInfos[0].setLayoutCount = 1; - shaderCreateInfos[0].pSetLayouts = &descriptorSetLayout; - - // FS - _loadShader(getShadersPath() + "shaderobjects/phong.frag.spv", shaderCodes[1], shaderCodeSizes[1]); - shaderCreateInfos[1].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT; - shaderCreateInfos[1].flags = VK_SHADER_CREATE_LINK_STAGE_BIT_EXT; - shaderCreateInfos[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderCreateInfos[1].nextStage = 0; - shaderCreateInfos[1].codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT; - shaderCreateInfos[1].pCode = shaderCodes[1]; - shaderCreateInfos[1].codeSize = shaderCodeSizes[1]; - shaderCreateInfos[1].pName = "main"; - shaderCreateInfos[1].setLayoutCount = 1; - shaderCreateInfos[1].pSetLayouts = &descriptorSetLayout; - - VK_CHECK_RESULT(vkCreateShadersEXT(device, 2, shaderCreateInfos, nullptr, shaders)); - - // Store the binary shader files so we can try to load them at the next start - size_t dataSize{ 0 }; - char* data{ nullptr }; - std::fstream is; - - vkGetShaderBinaryDataEXT(device, shaders[0], &dataSize, nullptr); - data = new char[dataSize]; - vkGetShaderBinaryDataEXT(device, shaders[0], &dataSize, data); - is.open(getShadersPath() + "shaderobjects/phong.vert.bin", std::ios::binary | std::ios::out); - is.write(data, dataSize); - is.close(); - delete[] data; - - vkGetShaderBinaryDataEXT(device, shaders[1], &dataSize, nullptr); - data = new char[dataSize]; - vkGetShaderBinaryDataEXT(device, shaders[1], &dataSize, data); - is.open(getShadersPath() + "shaderobjects/phong.frag.bin", std::ios::binary | std::ios::out); - is.write(data, dataSize); - is.close(); - delete[] data; - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Transition color and depth images for drawing - vks::tools::insertImageMemoryBarrier( - drawCmdBuffers[i], - swapChain.images[i], - 0, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - vks::tools::insertImageMemoryBarrier( - drawCmdBuffers[i], - depthStencil.image, - 0, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1 }); - - // New structures are used to define the attachments used in dynamic rendering - VkRenderingAttachmentInfoKHR colorAttachment{}; - colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; - colorAttachment.imageView = swapChain.imageViews[i]; - colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.clearValue.color = { 0.0f,0.0f,0.0f,0.0f }; - - // A single depth stencil attachment info can be used, but they can also be specified separately. - // When both are specified separately, the only requirement is that the image view is identical. - VkRenderingAttachmentInfoKHR depthStencilAttachment{}; - depthStencilAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; - depthStencilAttachment.imageView = depthStencil.view; - depthStencilAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - depthStencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - depthStencilAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - depthStencilAttachment.clearValue.depthStencil = { 1.0f, 0 }; - - VkRenderingInfoKHR renderingInfo{}; - renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR; - renderingInfo.renderArea = { 0, 0, width, height }; - renderingInfo.layerCount = 1; - renderingInfo.colorAttachmentCount = 1; - renderingInfo.pColorAttachments = &colorAttachment; - renderingInfo.pDepthAttachment = &depthStencilAttachment; - renderingInfo.pStencilAttachment = &depthStencilAttachment; - - // Begin dynamic rendering - vkCmdBeginRenderingKHR(drawCmdBuffers[i], &renderingInfo); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - - // No more pipelines required, everything is bound at command buffer level - // This also means that we need to explicitly set a lot of the state to be spec compliant - - vkCmdSetViewportWithCountEXT(drawCmdBuffers[i], 1, &viewport); - vkCmdSetScissorWithCountEXT(drawCmdBuffers[i], 1, &scissor); - vkCmdSetCullModeEXT(drawCmdBuffers[i], VK_CULL_MODE_BACK_BIT); - vkCmdSetFrontFaceEXT(drawCmdBuffers[i], VK_FRONT_FACE_COUNTER_CLOCKWISE); - vkCmdSetDepthTestEnableEXT(drawCmdBuffers[i], VK_TRUE); - vkCmdSetDepthWriteEnableEXT(drawCmdBuffers[i], VK_TRUE); - vkCmdSetDepthCompareOpEXT(drawCmdBuffers[i], VK_COMPARE_OP_LESS_OR_EQUAL); - vkCmdSetPrimitiveTopologyEXT(drawCmdBuffers[i], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); - vkCmdSetRasterizerDiscardEnableEXT(drawCmdBuffers[i], VK_FALSE); - vkCmdSetPolygonModeEXT(drawCmdBuffers[i], VK_POLYGON_MODE_FILL); - vkCmdSetRasterizationSamplesEXT(drawCmdBuffers[i], VK_SAMPLE_COUNT_1_BIT); - vkCmdSetAlphaToCoverageEnableEXT(drawCmdBuffers[i], VK_FALSE); - vkCmdSetDepthBiasEnableEXT(drawCmdBuffers[i], VK_FALSE); - vkCmdSetStencilTestEnableEXT(drawCmdBuffers[i], VK_FALSE); - vkCmdSetPrimitiveRestartEnableEXT(drawCmdBuffers[i], VK_FALSE); - - const uint32_t sampleMask = 0xFF; - vkCmdSetSampleMaskEXT(drawCmdBuffers[i], VK_SAMPLE_COUNT_1_BIT, &sampleMask); - - const VkBool32 colorBlendEnables = false; - const VkColorComponentFlags colorBlendComponentFlags = 0xf; - const VkColorBlendEquationEXT colorBlendEquation{}; - vkCmdSetColorBlendEnableEXT(drawCmdBuffers[i], 0, 1, &colorBlendEnables); - vkCmdSetColorWriteMaskEXT(drawCmdBuffers[i], 0, 1, &colorBlendComponentFlags); - - VkVertexInputBindingDescription2EXT vertexInputBinding{}; - vertexInputBinding.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT; - vertexInputBinding.binding = 0; - vertexInputBinding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - vertexInputBinding.stride = sizeof(vkglTF::Vertex); - vertexInputBinding.divisor = 1; - - std::vector vertexAttributes = { - { VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(vkglTF::Vertex, pos) }, - { VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, nullptr, 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(vkglTF::Vertex, normal) }, - { VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, nullptr, 2, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(vkglTF::Vertex, color) } - }; - - vkCmdSetVertexInputEXT(drawCmdBuffers[i], 1, &vertexInputBinding, 3, vertexAttributes.data()); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - scene.bindBuffers(drawCmdBuffers[i]); - - // Binding the shaders - VkShaderStageFlagBits stages[2] = { VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT }; - vkCmdBindShadersEXT(drawCmdBuffers[i], 2, stages, shaders); - scene.draw(drawCmdBuffers[i]); - - // @todo: Currently disabled, the UI needs to be adopated to work with shader objects - // drawUI(drawCmdBuffers[i]); - - // End dynamic rendering - vkCmdEndRenderingKHR(drawCmdBuffers[i]); - - // Transition color image for presentation - vks::tools::insertImageMemoryBarrier( - drawCmdBuffers[i], - swapChain.images[i], - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - 0, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Create the vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - updateUniformBuffers(); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - - // As this is an extension, we need to explicitly load the function pointers for the shader object commands used in this sample - - vkCreateShadersEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCreateShadersEXT")); - vkDestroyShaderEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkDestroyShaderEXT")); - vkCmdBindShadersEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBindShadersEXT")); - vkGetShaderBinaryDataEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetShaderBinaryDataEXT")); - - vkCmdBeginRenderingKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBeginRenderingKHR")); - vkCmdEndRenderingKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdEndRenderingKHR")); - - vkCmdSetAlphaToCoverageEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetAlphaToCoverageEnableEXT")); - vkCmdSetColorBlendEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetColorBlendEnableEXT")); - vkCmdSetColorWriteMaskEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetColorWriteMaskEXT")); - vkCmdSetCullModeEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetCullModeEXT")); - vkCmdSetDepthBiasEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetDepthBiasEnableEXT")); - vkCmdSetDepthCompareOpEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetDepthCompareOpEXT")); - vkCmdSetDepthTestEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetDepthTestEnableEXT")); - vkCmdSetDepthWriteEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetDepthWriteEnableEXT")); - vkCmdSetFrontFaceEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetFrontFaceEXT")); - vkCmdSetPolygonModeEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetPolygonModeEXT")); - vkCmdSetPrimitiveRestartEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetPrimitiveRestartEnableEXT")); - vkCmdSetPrimitiveTopologyEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetPrimitiveTopologyEXT")); - vkCmdSetRasterizationSamplesEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetRasterizationSamplesEXT")); - vkCmdSetRasterizerDiscardEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetRasterizerDiscardEnableEXT")); - vkCmdSetSampleMaskEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetSampleMaskEXT")); - vkCmdSetScissorWithCountEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetScissorWithCountEXT")); - vkCmdSetStencilTestEnableEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetStencilTestEnableEXT")); - vkCmdSetVertexInputEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetVertexInputEXT")); - vkCmdSetViewportWithCountEXT = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetViewportWithCountEXT"));; - - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - createShaderObjects(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - draw(); - updateUniformBuffers(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/shadowmapping/shadowmapping.cpp b/examples/shadowmapping/shadowmapping.cpp deleted file mode 100644 index 59d9474e..00000000 --- a/examples/shadowmapping/shadowmapping.cpp +++ /dev/null @@ -1,598 +0,0 @@ -/* -* Vulkan Example - Shadow mapping for directional light sources -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool displayShadowMap = false; - bool filterPCF = true; - - // Keep depth range as small as possible - // for better shadow map precision - float zNear = 1.0f; - float zFar = 96.0f; - - // Depth bias (and slope) are used to avoid shadowing artifacts - // Constant depth bias factor (always applied) - float depthBiasConstant = 1.25f; - // Slope depth bias factor, applied depending on polygon's slope - float depthBiasSlope = 1.75f; - - glm::vec3 lightPos = glm::vec3(); - float lightFOV = 45.0f; - - std::vector scenes; - std::vector sceneNames; - int32_t sceneIndex = 0; - - struct UniformDataScene { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - glm::mat4 depthBiasMVP; - glm::vec4 lightPos; - // Used for depth map visualization - float zNear; - float zFar; - } uniformDataScene; - - struct UniformDataOffscreen { - glm::mat4 depthMVP; - } uniformDataOffscreen; - - struct { - vks::Buffer scene; - vks::Buffer offscreen; - } uniformBuffers; - - struct { - VkPipeline offscreen{ VK_NULL_HANDLE }; - VkPipeline sceneShadow{ VK_NULL_HANDLE }; - // Pipeline with percentage close filtering (PCF) of the shadow map - VkPipeline sceneShadowPCF{ VK_NULL_HANDLE }; - VkPipeline debug{ VK_NULL_HANDLE }; - } pipelines; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - - struct { - VkDescriptorSet offscreen{ VK_NULL_HANDLE }; - VkDescriptorSet scene{ VK_NULL_HANDLE }; - VkDescriptorSet debug{ VK_NULL_HANDLE }; - } descriptorSets; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - // Framebuffer for offscreen rendering - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory mem; - VkImageView view; - }; - struct OffscreenPass { - int32_t width, height; - VkFramebuffer frameBuffer; - FrameBufferAttachment depth; - VkRenderPass renderPass; - VkSampler depthSampler; - VkDescriptorImageInfo descriptor; - } offscreenPass{}; - - // 16 bits of depth is enough for such a small scene - const VkFormat offscreenDepthFormat{ VK_FORMAT_D16_UNORM }; - // Shadow map dimension -#if defined(__ANDROID__) - // Use a smaller size on Android for performance reasons - const uint32_t shadowMapize{ 1024 }; -#else - const uint32_t shadowMapize{ 2048 }; -#endif - - VulkanExample() : VulkanExampleBase() - { - title = "Projected shadow mapping"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -12.5f)); - camera.setRotation(glm::vec3(-25.0f, -390.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 1.0f, 256.0f); - timerSpeed *= 0.5f; - } - - ~VulkanExample() - { - if (device) { - // Frame buffer - vkDestroySampler(device, offscreenPass.depthSampler, nullptr); - - // Depth attachment - vkDestroyImageView(device, offscreenPass.depth.view, nullptr); - vkDestroyImage(device, offscreenPass.depth.image, nullptr); - vkFreeMemory(device, offscreenPass.depth.mem, nullptr); - - vkDestroyFramebuffer(device, offscreenPass.frameBuffer, nullptr); - - vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); - - vkDestroyPipeline(device, pipelines.debug, nullptr); - vkDestroyPipeline(device, pipelines.offscreen, nullptr); - vkDestroyPipeline(device, pipelines.sceneShadow, nullptr); - vkDestroyPipeline(device, pipelines.sceneShadowPCF, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - // Uniform buffers - uniformBuffers.offscreen.destroy(); - uniformBuffers.scene.destroy(); - } - } - - // Set up a separate render pass for the offscreen frame buffer - // This is necessary as the offscreen frame buffer attachments use formats different to those from the example render pass - void prepareOffscreenRenderpass() - { - VkAttachmentDescription attachmentDescription{}; - attachmentDescription.format = offscreenDepthFormat; - attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; - attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at beginning of the render pass - attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // We will read from depth, so it's important to store the depth attachment results - attachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // We don't care about initial layout of the attachment - attachmentDescription.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;// Attachment will be transitioned to shader read at render pass end - - VkAttachmentReference depthReference = {}; - depthReference.attachment = 0; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Attachment will be used as depth/stencil during render pass - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 0; // No color attachments - subpass.pDepthStencilAttachment = &depthReference; // Reference to our depth attachment - - // Use subpass dependencies for layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassCreateInfo = vks::initializers::renderPassCreateInfo(); - renderPassCreateInfo.attachmentCount = 1; - renderPassCreateInfo.pAttachments = &attachmentDescription; - renderPassCreateInfo.subpassCount = 1; - renderPassCreateInfo.pSubpasses = &subpass; - renderPassCreateInfo.dependencyCount = static_cast(dependencies.size()); - renderPassCreateInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, &offscreenPass.renderPass)); - } - - // Setup the offscreen framebuffer for rendering the scene from light's point-of-view to - // The depth attachment of this framebuffer will then be used to sample from in the fragment shader of the shadowing pass - void prepareOffscreenFramebuffer() - { - offscreenPass.width = shadowMapize; - offscreenPass.height = shadowMapize; - - // For shadow mapping we only need a depth attachment - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.extent.width = offscreenPass.width; - image.extent.height = offscreenPass.height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.format = offscreenDepthFormat; // Depth stencil attachment - image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; // We will sample directly from the depth attachment for the shadow mapping - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.depth.image)); - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0)); - - VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo(); - depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilView.format = offscreenDepthFormat; - depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - depthStencilView.subresourceRange.baseMipLevel = 0; - depthStencilView.subresourceRange.levelCount = 1; - depthStencilView.subresourceRange.baseArrayLayer = 0; - depthStencilView.subresourceRange.layerCount = 1; - depthStencilView.image = offscreenPass.depth.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view)); - - // Create sampler to sample from to depth attachment - // Used to sample in the fragment shader for shadowed rendering - VkFilter shadowmap_filter = vks::tools::formatIsFilterable(physicalDevice, offscreenDepthFormat, VK_IMAGE_TILING_OPTIMAL) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = shadowmap_filter; - sampler.minFilter = shadowmap_filter; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 1.0f; - sampler.minLod = 0.0f; - sampler.maxLod = 1.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &offscreenPass.depthSampler)); - - prepareOffscreenRenderpass(); - - // Create frame buffer - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = offscreenPass.renderPass; - fbufCreateInfo.attachmentCount = 1; - fbufCreateInfo.pAttachments = &offscreenPass.depth.view; - fbufCreateInfo.width = offscreenPass.width; - fbufCreateInfo.height = offscreenPass.height; - fbufCreateInfo.layers = 1; - - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreenPass.frameBuffer)); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - VkViewport viewport; - VkRect2D scissor; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - First render pass: Generate shadow map by rendering the scene from light's POV - */ - { - clearValues[0].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = offscreenPass.renderPass; - renderPassBeginInfo.framebuffer = offscreenPass.frameBuffer; - renderPassBeginInfo.renderArea.extent.width = offscreenPass.width; - renderPassBeginInfo.renderArea.extent.height = offscreenPass.height; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - viewport = vks::initializers::viewport((float)offscreenPass.width, (float)offscreenPass.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - scissor = vks::initializers::rect2D(offscreenPass.width, offscreenPass.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Set depth bias (aka "Polygon offset") - // Required to avoid shadow mapping artifacts - vkCmdSetDepthBias( - drawCmdBuffers[i], - depthBiasConstant, - 0.0f, - depthBiasSlope); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.offscreen); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.offscreen, 0, nullptr); - scenes[sceneIndex].draw(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Second pass: Scene rendering with applied shadow map - */ - - { - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Visualize shadow map - if (displayShadowMap) { - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.debug, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.debug); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - } else { - // Render the shadows scene - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.scene, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, (filterPCF) ? pipelines.sceneShadowPCF : pipelines.sceneShadow); - scenes[sceneIndex].draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - scenes.resize(2); - scenes[0].loadFromFile(getAssetPath() + "models/vulkanscene_shadow.gltf", vulkanDevice, queue, glTFLoadingFlags); - scenes[1].loadFromFile(getAssetPath() + "models/samplescene.gltf", vulkanDevice, queue, glTFLoadingFlags); - sceneNames = {"Vulkan scene", "Teapots and pillars" }; - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // Binding 1 : Fragment shader image sampler (shadow map) - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - std::vector writeDescriptorSets; - - // Image descriptor for the shadow map attachment - VkDescriptorImageInfo shadowMapDescriptor = - vks::initializers::descriptorImageInfo( - offscreenPass.depthSampler, - offscreenPass.depth.view, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); - - // Debug display - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.debug)); - writeDescriptorSets = { - // Binding 0 : Parameters uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.debug, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor), - // Binding 1 : Fragment shader texture sampler - vks::initializers::writeDescriptorSet(descriptorSets.debug, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &shadowMapDescriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Offscreen shadow map generation - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.offscreen)); - writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.offscreen, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.offscreen.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Scene rendering with shadow map applied - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.scene)); - writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor), - // Binding 1 : Fragment shader shadow sampler - vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &shadowMapDescriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Shadow mapping debug quad display - rasterizationStateCI.cullMode = VK_CULL_MODE_NONE; - shaderStages[0] = loadShader(getShadersPath() + "shadowmapping/quad.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "shadowmapping/quad.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Empty vertex input state - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCI.pVertexInputState = &emptyInputState; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.debug)); - - // Scene rendering with shadows applied - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal}); - rasterizationStateCI.cullMode = VK_CULL_MODE_BACK_BIT; - shaderStages[0] = loadShader(getShadersPath() + "shadowmapping/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "shadowmapping/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Use specialization constants to select between horizontal and vertical blur - uint32_t enablePCF = 0; - VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t)); - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(uint32_t), &enablePCF); - shaderStages[1].pSpecializationInfo = &specializationInfo; - // No filtering - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.sceneShadow)); - // PCF filtering - enablePCF = 1; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.sceneShadowPCF)); - - // Offscreen pipeline (vertex shader only) - shaderStages[0] = loadShader(getShadersPath() + "shadowmapping/offscreen.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - pipelineCI.stageCount = 1; - // No blend attachment states (no color attachments used) - colorBlendStateCI.attachmentCount = 0; - // Disable culling, so all faces contribute to shadows - rasterizationStateCI.cullMode = VK_CULL_MODE_NONE; - depthStencilStateCI.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; - // Enable depth bias - rasterizationStateCI.depthBiasEnable = VK_TRUE; - // Add depth bias to dynamic state, so we can change it at runtime - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_DEPTH_BIAS); - dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - pipelineCI.renderPass = offscreenPass.renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.offscreen)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Offscreen vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.offscreen, sizeof(UniformDataOffscreen))); - // Scene vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.scene, sizeof(UniformDataScene))); - // Map persistent - VK_CHECK_RESULT(uniformBuffers.offscreen.map()); - VK_CHECK_RESULT(uniformBuffers.scene.map()); - - updateLight(); - updateUniformBufferOffscreen(); - updateUniformBuffers(); - } - - void updateLight() - { - // Animate the light source - lightPos.x = cos(glm::radians(timer * 360.0f)) * 40.0f; - lightPos.y = -50.0f + sin(glm::radians(timer * 360.0f)) * 20.0f; - lightPos.z = 25.0f + sin(glm::radians(timer * 360.0f)) * 5.0f; - } - - void updateUniformBuffers() - { - uniformDataScene.projection = camera.matrices.perspective; - uniformDataScene.view = camera.matrices.view; - uniformDataScene.model = glm::mat4(1.0f); - uniformDataScene.lightPos = glm::vec4(lightPos, 1.0f); - uniformDataScene.depthBiasMVP = uniformDataOffscreen.depthMVP; - uniformDataScene.zNear = zNear; - uniformDataScene.zFar = zFar; - memcpy(uniformBuffers.scene.mapped, &uniformDataScene, sizeof(uniformDataScene)); - } - - void updateUniformBufferOffscreen() - { - // Matrix from light's point of view - glm::mat4 depthProjectionMatrix = glm::perspective(glm::radians(lightFOV), 1.0f, zNear, zFar); - glm::mat4 depthViewMatrix = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0, 1, 0)); - glm::mat4 depthModelMatrix = glm::mat4(1.0f); - - uniformDataOffscreen.depthMVP = depthProjectionMatrix * depthViewMatrix * depthModelMatrix; - - memcpy(uniformBuffers.offscreen.mapped, &uniformDataOffscreen, sizeof(uniformDataOffscreen)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareOffscreenFramebuffer(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - if (!paused || camera.updated) { - updateLight(); - updateUniformBufferOffscreen(); - updateUniformBuffers(); - } - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->comboBox("Scenes", &sceneIndex, sceneNames)) { - buildCommandBuffers(); - } - if (overlay->checkBox("Display shadow render target", &displayShadowMap)) { - buildCommandBuffers(); - } - if (overlay->checkBox("PCF filtering", &filterPCF)) { - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/shadowmappingcascade/shadowmappingcascade.cpp b/examples/shadowmappingcascade/shadowmappingcascade.cpp deleted file mode 100644 index 55c6328b..00000000 --- a/examples/shadowmappingcascade/shadowmappingcascade.cpp +++ /dev/null @@ -1,785 +0,0 @@ -/* - Vulkan Example - Cascaded shadow mapping for directional light sources - Copyright (c) 2016-2025 by Sascha Willems - www.saschawillems.de - This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - - This example implements projective cascaded shadow mapping. This technique splits up the camera frustum into - multiple frustums with each getting its own full-res shadow map, implemented as a layered depth-only image. - The shader then selects the proper shadow map layer depending on what split of the frustum the depth value - to compare fits into. - - This results in a better shadow map resolution distribution that can be tweaked even further by increasing - the number of frustum splits. - - A further optimization could be done using a geometry shader to do a single-pass render for the depth map - cascades instead of multiple passes (geometry shaders are not supported on all target devices). -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -#if defined(__ANDROID__) -#define SHADOWMAP_DIM 2048 -#else -#define SHADOWMAP_DIM 4096 -#endif - -#define SHADOW_MAP_CASCADE_COUNT 4 - -class VulkanExample : public VulkanExampleBase -{ -public: - bool displayDepthMap = false; - int32_t displayDepthMapCascadeIndex = 0; - bool colorCascades = false; - bool filterPCF = false; - - float cascadeSplitLambda = 0.95f; - - float zNear = 0.5f; - float zFar = 48.0f; - - glm::vec3 lightPos = glm::vec3(); - - struct Models { - vkglTF::Model terrain; - vkglTF::Model tree; - } models; - - struct uniformBuffers { - vks::Buffer VS; - vks::Buffer FS; - } uniformBuffers; - - struct UBOVS { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - glm::vec3 lightDir; - } uboVS; - - struct UBOFS { - float cascadeSplits[4]; - glm::mat4 inverseViewMat; - glm::vec3 lightDir; - float _pad; - int32_t colorCascades; - } uboFS; - - VkPipelineLayout pipelineLayout; - struct Pipelines { - VkPipeline debugShadowMap; - VkPipeline sceneShadow; - VkPipeline sceneShadowPCF; - } pipelines; - - VkDescriptorSetLayout descriptorSetLayout; - VkDescriptorSet descriptorSet; - - // For simplicity all pipelines use the same push constant block layout - struct PushConstBlock { - glm::vec4 position; - uint32_t cascadeIndex; - }; - - // Resources of the depth map generation pass - struct DepthPass { - VkRenderPass renderPass; - VkPipelineLayout pipelineLayout; - VkPipeline pipeline; - } depthPass; - - // Layered depth image containing the shadow cascade depths - struct DepthImage { - VkImage image; - VkDeviceMemory mem; - VkImageView view; - VkSampler sampler; - void destroy(VkDevice device) { - vkDestroyImageView(device, view, nullptr); - vkDestroyImage(device, image, nullptr); - vkFreeMemory(device, mem, nullptr); - vkDestroySampler(device, sampler, nullptr); - } - } depth; - - // Contains all resources required for a single shadow map cascade - struct Cascade { - VkFramebuffer frameBuffer; - VkImageView view; - float splitDepth; - glm::mat4 viewProjMatrix; - void destroy(VkDevice device) { - vkDestroyImageView(device, view, nullptr); - vkDestroyFramebuffer(device, frameBuffer, nullptr); - } - }; - std::array cascades; - // Per-cascade matrices will be passed to the shaders as a linear array - vks::Buffer cascadeViewProjMatricesBuffer; - - VulkanExample() : VulkanExampleBase() - { - title = "Cascaded shadow mapping"; - timerSpeed *= 0.025f; - camera.type = Camera::CameraType::firstperson; - camera.movementSpeed = 2.5f; - camera.setPerspective(45.0f, (float)width / (float)height, zNear, zFar); - camera.setPosition(glm::vec3(-0.12f, 1.14f, -2.25f)); - camera.setRotation(glm::vec3(-17.0f, 7.0f, 0.0f)); - timer = 0.2f; - } - - ~VulkanExample() - { - for (auto cascade : cascades) { - cascade.destroy(device); - } - depth.destroy(device); - - vkDestroyRenderPass(device, depthPass.renderPass, nullptr); - - vkDestroyPipeline(device, pipelines.debugShadowMap, nullptr); - vkDestroyPipeline(device, depthPass.pipeline, nullptr); - vkDestroyPipeline(device, pipelines.sceneShadow, nullptr); - vkDestroyPipeline(device, pipelines.sceneShadowPCF, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyPipelineLayout(device, depthPass.pipelineLayout, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - cascadeViewProjMatricesBuffer.destroy(); - uniformBuffers.VS.destroy(); - uniformBuffers.FS.destroy(); - } - - virtual void getEnabledFeatures() - { - enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy; - // Depth clamp to avoid near plane clipping - enabledFeatures.depthClamp = deviceFeatures.depthClamp; - } - - /* - Render the example scene to acommand buffer using the supplied pipeline layout and for the selected shadow cascade index - Used by the scene rendering and depth pass generation command buffer - */ - void renderScene(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, uint32_t cascadeIndex = 0) { - // We use push constants for passing shadow cascade info to the shaders - PushConstBlock pushConstBlock = { glm::vec4(0.0f), cascadeIndex }; - - // Set 0 contains the vertex and fragment shader uniform buffers, set 1 for images will be set by the glTF model class at draw time - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - // Floor - vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstBlock), &pushConstBlock); - models.terrain.draw(commandBuffer, vkglTF::RenderFlags::BindImages, pipelineLayout); - - // Trees - const std::vector positions = { - glm::vec3(0.0f, 0.0f, 0.0f), - glm::vec3(1.25f, 0.25f, 1.25f), - glm::vec3(-1.25f, -0.2f, 1.25f), - glm::vec3(1.25f, 0.1f, -1.25f), - glm::vec3(-1.25f, -0.25f, -1.25f), - }; - - for (auto& position : positions) { - pushConstBlock.position = glm::vec4(position, 0.0f); - vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstBlock), &pushConstBlock); - // This will also bind the texture images to set 1 - models.tree.draw(commandBuffer, vkglTF::RenderFlags::BindImages, pipelineLayout); - } - } - - /* - Setup resources used by the depth pass - The depth image is layered with each layer storing one shadow map cascade - */ - void prepareDepthPass() - { - VkFormat depthFormat = vulkanDevice->getSupportedDepthFormat(true); - - /* - Depth map renderpass - */ - - VkAttachmentDescription attachmentDescription{}; - attachmentDescription.format = depthFormat; - attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; - attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachmentDescription.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - - VkAttachmentReference depthReference = {}; - depthReference.attachment = 0; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 0; - subpass.pDepthStencilAttachment = &depthReference; - - // Use subpass dependencies for layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassCreateInfo = vks::initializers::renderPassCreateInfo(); - renderPassCreateInfo.attachmentCount = 1; - renderPassCreateInfo.pAttachments = &attachmentDescription; - renderPassCreateInfo.subpassCount = 1; - renderPassCreateInfo.pSubpasses = &subpass; - renderPassCreateInfo.dependencyCount = static_cast(dependencies.size()); - renderPassCreateInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, &depthPass.renderPass)); - - /* - Layered depth image and views - */ - - VkImageCreateInfo imageInfo = vks::initializers::imageCreateInfo(); - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.extent.width = SHADOWMAP_DIM; - imageInfo.extent.height = SHADOWMAP_DIM; - imageInfo.extent.depth = 1; - imageInfo.mipLevels = 1; - imageInfo.arrayLayers = SHADOW_MAP_CASCADE_COUNT; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.format = depthFormat; - imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageInfo, nullptr, &depth.image)); - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, depth.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depth.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, depth.image, depth.mem, 0)); - // Full depth map view (all layers) - VkImageViewCreateInfo viewInfo = vks::initializers::imageViewCreateInfo(); - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - viewInfo.format = depthFormat; - viewInfo.subresourceRange = {}; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.baseArrayLayer = 0; - viewInfo.subresourceRange.layerCount = SHADOW_MAP_CASCADE_COUNT; - viewInfo.image = depth.image; - VK_CHECK_RESULT(vkCreateImageView(device, &viewInfo, nullptr, &depth.view)); - - // One image view and framebuffer per cascade - for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) { - // Image view for this cascade's layer (inside the depth map) - // This view is used to render to that specific depth image layer - VkImageViewCreateInfo viewInfo = vks::initializers::imageViewCreateInfo(); - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - viewInfo.format = depthFormat; - viewInfo.subresourceRange = {}; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.baseArrayLayer = i; - viewInfo.subresourceRange.layerCount = 1; - viewInfo.image = depth.image; - VK_CHECK_RESULT(vkCreateImageView(device, &viewInfo, nullptr, &cascades[i].view)); - // Framebuffer - VkFramebufferCreateInfo framebufferInfo = vks::initializers::framebufferCreateInfo(); - framebufferInfo.renderPass = depthPass.renderPass; - framebufferInfo.attachmentCount = 1; - framebufferInfo.pAttachments = &cascades[i].view; - framebufferInfo.width = SHADOWMAP_DIM; - framebufferInfo.height = SHADOWMAP_DIM; - framebufferInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &framebufferInfo, nullptr, &cascades[i].frameBuffer)); - } - - // Shared sampler for cascade depth reads - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 1.0f; - sampler.minLod = 0.0f; - sampler.maxLod = 1.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &depth.sampler)); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - for (int32_t i = 0; i < drawCmdBuffers.size(); i++) { - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Generate depth map cascades - - Uses multiple passes with each pass rendering the scene to the cascade's depth image layer - Could be optimized using a geometry shader (and layered frame buffer) on devices that support geometry shaders - */ - { - VkClearValue clearValues[1]; - clearValues[0].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = depthPass.renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = SHADOWMAP_DIM; - renderPassBeginInfo.renderArea.extent.height = SHADOWMAP_DIM; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = clearValues; - - VkViewport viewport = vks::initializers::viewport((float)SHADOWMAP_DIM, (float)SHADOWMAP_DIM, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(SHADOWMAP_DIM, SHADOWMAP_DIM, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // One pass per cascade - for (uint32_t j = 0; j < SHADOW_MAP_CASCADE_COUNT; j++) { - renderPassBeginInfo.framebuffer = cascades[j].frameBuffer; - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, depthPass.pipeline); - renderScene(drawCmdBuffers[i], depthPass.pipelineLayout, j); - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - } - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Scene rendering using depth cascades for shadow mapping - */ - - { - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Visualize shadow map cascade - if (displayDepthMap) { - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.debugShadowMap); - PushConstBlock pushConstBlock = {}; - pushConstBlock.cascadeIndex = displayDepthMapCascadeIndex; - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstBlock), &pushConstBlock); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - } - - // Render shadowed scene - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, (filterPCF) ? pipelines.sceneShadowPCF : pipelines.sceneShadow); - renderScene(drawCmdBuffers[i], pipelineLayout); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY; - models.terrain.loadFromFile(getAssetPath() + "models/terrain_gridlines.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.tree.loadFromFile(getAssetPath() + "models/oaktree.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupLayoutsAndDescriptors() - { - /* - Descriptor pool - */ - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 32), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 32) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = - vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), 4 + SHADOW_MAP_CASCADE_COUNT); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - /* - Descriptor set layouts - */ - - // Shared matrices and samplers - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 3), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - /* - Descriptor sets - */ - - VkDescriptorImageInfo depthMapDescriptor = - vks::initializers::descriptorImageInfo(depth.sampler, depth.view, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); - - VkDescriptorSetAllocateInfo allocInfo = - vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - // Scene rendering / debug display - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - const std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.VS.descriptor), - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &depthMapDescriptor), - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &uniformBuffers.FS.descriptor), - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3, &cascadeViewProjMatricesBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - - /* - Pipeline layouts - */ - - // Shared pipeline layout (scene and depth map debug display) - { - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushConstBlock), 0); - std::array setLayouts = { descriptorSetLayout, vkglTF::descriptorSetLayoutImage }; - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - } - - // Depth pass pipeline layout - { - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushConstBlock), 0); - std::array setLayouts = { descriptorSetLayout, vkglTF::descriptorSetLayoutImage }; - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &depthPass.pipelineLayout)); - } - } - - void preparePipelines() - { - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Shadow map cascade debug quad display - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - shaderStages[0] = loadShader(getShadersPath() + "shadowmappingcascade/debugshadowmap.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "shadowmappingcascade/debugshadowmap.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Empty vertex input state - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCI.pVertexInputState = &emptyInputState; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.debugShadowMap)); - - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal }); - /* - Shadow mapped scene rendering - */ - rasterizationState.cullMode = VK_CULL_MODE_NONE; - shaderStages[0] = loadShader(getShadersPath() + "shadowmappingcascade/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "shadowmappingcascade/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Use specialization constants to select between horizontal and vertical blur - uint32_t enablePCF = 0; - VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t)); - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(uint32_t), &enablePCF); - shaderStages[1].pSpecializationInfo = &specializationInfo; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.sceneShadow)); - enablePCF = 1; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.sceneShadowPCF)); - - /* - Depth map generation - */ - shaderStages[0] = loadShader(getShadersPath() + "shadowmappingcascade/depthpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "shadowmappingcascade/depthpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // No blend attachment states (no color attachments used) - colorBlendState.attachmentCount = 0; - depthStencilState.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; - // Enable depth clamp (if available) - rasterizationState.depthClampEnable = deviceFeatures.depthClamp; - pipelineCI.layout = depthPass.pipelineLayout; - pipelineCI.renderPass = depthPass.renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &depthPass.pipeline)); - } - - void prepareUniformBuffers() - { - // Cascade matrices - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &cascadeViewProjMatricesBuffer, - sizeof(glm::mat4) * SHADOW_MAP_CASCADE_COUNT)); - - // Scene uniform buffer blocks - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.VS, - sizeof(uboVS))); - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.FS, - sizeof(uboFS))); - - // Map persistent - VK_CHECK_RESULT(cascadeViewProjMatricesBuffer.map()); - VK_CHECK_RESULT(uniformBuffers.VS.map()); - VK_CHECK_RESULT(uniformBuffers.FS.map()); - - updateLight(); - updateUniformBuffers(); - } - - /* - Calculate frustum split depths and matrices for the shadow map cascades - Based on https://johanmedestrom.wordpress.com/2016/03/18/opengl-cascaded-shadow-maps/ - */ - void updateCascades() - { - float cascadeSplits[SHADOW_MAP_CASCADE_COUNT]; - - float nearClip = camera.getNearClip(); - float farClip = camera.getFarClip(); - float clipRange = farClip - nearClip; - - float minZ = nearClip; - float maxZ = nearClip + clipRange; - - float range = maxZ - minZ; - float ratio = maxZ / minZ; - - // Calculate split depths based on view camera frustum - // Based on method presented in https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch10.html - for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) { - float p = (i + 1) / static_cast(SHADOW_MAP_CASCADE_COUNT); - float log = minZ * std::pow(ratio, p); - float uniform = minZ + range * p; - float d = cascadeSplitLambda * (log - uniform) + uniform; - cascadeSplits[i] = (d - nearClip) / clipRange; - } - - // Calculate orthographic projection matrix for each cascade - float lastSplitDist = 0.0; - for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) { - float splitDist = cascadeSplits[i]; - - glm::vec3 frustumCorners[8] = { - glm::vec3(-1.0f, 1.0f, 0.0f), - glm::vec3( 1.0f, 1.0f, 0.0f), - glm::vec3( 1.0f, -1.0f, 0.0f), - glm::vec3(-1.0f, -1.0f, 0.0f), - glm::vec3(-1.0f, 1.0f, 1.0f), - glm::vec3( 1.0f, 1.0f, 1.0f), - glm::vec3( 1.0f, -1.0f, 1.0f), - glm::vec3(-1.0f, -1.0f, 1.0f), - }; - - // Project frustum corners into world space - glm::mat4 invCam = glm::inverse(camera.matrices.perspective * camera.matrices.view); - for (uint32_t j = 0; j < 8; j++) { - glm::vec4 invCorner = invCam * glm::vec4(frustumCorners[j], 1.0f); - frustumCorners[j] = invCorner / invCorner.w; - } - - for (uint32_t j = 0; j < 4; j++) { - glm::vec3 dist = frustumCorners[j + 4] - frustumCorners[j]; - frustumCorners[j + 4] = frustumCorners[j] + (dist * splitDist); - frustumCorners[j] = frustumCorners[j] + (dist * lastSplitDist); - } - - // Get frustum center - glm::vec3 frustumCenter = glm::vec3(0.0f); - for (uint32_t j = 0; j < 8; j++) { - frustumCenter += frustumCorners[j]; - } - frustumCenter /= 8.0f; - - float radius = 0.0f; - for (uint32_t j = 0; j < 8; j++) { - float distance = glm::length(frustumCorners[j] - frustumCenter); - radius = glm::max(radius, distance); - } - radius = std::ceil(radius * 16.0f) / 16.0f; - - glm::vec3 maxExtents = glm::vec3(radius); - glm::vec3 minExtents = -maxExtents; - - glm::vec3 lightDir = normalize(-lightPos); - glm::mat4 lightViewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, glm::vec3(0.0f, 1.0f, 0.0f)); - glm::mat4 lightOrthoMatrix = glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f, maxExtents.z - minExtents.z); - - // Store split distance and matrix in cascade - cascades[i].splitDepth = (camera.getNearClip() + splitDist * clipRange) * -1.0f; - cascades[i].viewProjMatrix = lightOrthoMatrix * lightViewMatrix; - - lastSplitDist = cascadeSplits[i]; - } - } - - void updateLight() - { - float angle = glm::radians(timer * 360.0f); - float radius = 20.0f; - lightPos = glm::vec3(cos(angle) * radius, -radius, sin(angle) * radius); - } - - void updateUniformBuffers() - { - /* - Depth rendering - */ - std::vector cascadeViewProjMatrices(SHADOW_MAP_CASCADE_COUNT); - for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) { - cascadeViewProjMatrices[i] = cascades[i].viewProjMatrix; - } - memcpy(cascadeViewProjMatricesBuffer.mapped, cascadeViewProjMatrices.data(), sizeof(glm::mat4) * SHADOW_MAP_CASCADE_COUNT); - - /* - Scene rendering - */ - uboVS.projection = camera.matrices.perspective; - uboVS.view = camera.matrices.view; - uboVS.model = glm::mat4(1.0f); - uboVS.lightDir = normalize(-lightPos); - memcpy(uniformBuffers.VS.mapped, &uboVS, sizeof(uboVS)); - for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) { - uboFS.cascadeSplits[i] = cascades[i].splitDepth; - } - uboFS.inverseViewMat = glm::inverse(camera.matrices.view); - uboFS.lightDir = normalize(-lightPos); - uboFS.colorCascades = colorCascades; - memcpy(uniformBuffers.FS.mapped, &uboFS, sizeof(uboFS)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - updateLight(); - updateCascades(); - prepareDepthPass(); - prepareUniformBuffers(); - setupLayoutsAndDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - draw(); - if (!paused || camera.updated) { - updateLight(); - updateCascades(); - updateUniformBuffers(); - } - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->sliderFloat("Split lambda", &cascadeSplitLambda, 0.1f, 1.0f)) { - updateCascades(); - updateUniformBuffers(); - } - if (overlay->checkBox("Color cascades", &colorCascades)) { - updateUniformBuffers(); - } - if (overlay->checkBox("Display depth map", &displayDepthMap)) { - buildCommandBuffers(); - } - if (displayDepthMap) { - if (overlay->sliderInt("Cascade", &displayDepthMapCascadeIndex, 0, SHADOW_MAP_CASCADE_COUNT - 1)) { - buildCommandBuffers(); - } - } - if (overlay->checkBox("PCF filtering", &filterPCF)) { - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/shadowmappingomni/shadowmappingomni.cpp b/examples/shadowmappingomni/shadowmappingomni.cpp deleted file mode 100644 index 123e5293..00000000 --- a/examples/shadowmappingomni/shadowmappingomni.cpp +++ /dev/null @@ -1,708 +0,0 @@ -/* -* Vulkan Example - Omni directional shadows using a dynamic cube map -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool displayCubeMap{ false }; - - // Defines the depth range used for the shadow maps - // This should be kept as small as possible for precision - float zNear{ 0.1f }; - float zFar{ 1024.0f }; - - struct { - vkglTF::Model scene; - vkglTF::Model debugcube; - } models; - - glm::vec4 lightPos = glm::vec4(0.0f, -2.5f, 0.0f, 1.0); - - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - glm::vec4 lightPos; - }; - UniformData uniformDataScene, uniformDataOffscreen; - - struct { - vks::Buffer scene; - vks::Buffer offscreen; - } uniformBuffers; - - struct { - VkPipeline scene{ VK_NULL_HANDLE }; - VkPipeline offscreen{ VK_NULL_HANDLE }; - VkPipeline cubemapDisplay{ VK_NULL_HANDLE }; - } pipelines; - - struct { - VkPipelineLayout scene{ VK_NULL_HANDLE }; - VkPipelineLayout offscreen{ VK_NULL_HANDLE }; - } pipelineLayouts; - - struct { - VkDescriptorSet scene{ VK_NULL_HANDLE }; - VkDescriptorSet offscreen{ VK_NULL_HANDLE }; - } descriptorSets; - - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - vks::Texture shadowCubeMap; - std::array shadowCubeMapFaceImageViews{}; - - // Framebuffer for offscreen rendering - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory mem; - VkImageView view; - }; - struct OffscreenPass { - int32_t width, height; - std::array frameBuffers; - FrameBufferAttachment depth; - VkRenderPass renderPass; - VkSampler sampler; - VkDescriptorImageInfo descriptor; - } offscreenPass; - - // Size of the shadow map texture (per face) - const uint32_t offscreenImageSize{ 1024 }; - // We use a 32 bit float format for max. precision. Depending on the use case, lower precision may be fine and can save bandwidth - const VkFormat offscreenImageFormat{ VK_FORMAT_R32_SFLOAT }; - // The depth format is selected at runtime - VkFormat offscreenDepthFormat{ VK_FORMAT_UNDEFINED }; - - VulkanExample() : VulkanExampleBase() - { - title = "Point light shadows (cubemap)"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(45.0f, (float)width / (float)height, zNear, zFar); - camera.setRotation(glm::vec3(-20.5f, -673.0f, 0.0f)); - camera.setPosition(glm::vec3(0.0f, 0.5f, -15.0f)); - timerSpeed *= 0.5f; - } - - ~VulkanExample() - { - if (device) { - // Cube map - for (uint32_t i = 0; i < 6; i++) { - vkDestroyImageView(device, shadowCubeMapFaceImageViews[i], nullptr); - } - - vkDestroyImageView(device, shadowCubeMap.view, nullptr); - vkDestroyImage(device, shadowCubeMap.image, nullptr); - vkDestroySampler(device, shadowCubeMap.sampler, nullptr); - vkFreeMemory(device, shadowCubeMap.deviceMemory, nullptr); - - // Depth attachment - vkDestroyImageView(device, offscreenPass.depth.view, nullptr); - vkDestroyImage(device, offscreenPass.depth.image, nullptr); - vkFreeMemory(device, offscreenPass.depth.mem, nullptr); - - for (uint32_t i = 0; i < 6; i++) - { - vkDestroyFramebuffer(device, offscreenPass.frameBuffers[i], nullptr); - } - - vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); - - // Pipelines - vkDestroyPipeline(device, pipelines.scene, nullptr); - vkDestroyPipeline(device, pipelines.offscreen, nullptr); - vkDestroyPipeline(device, pipelines.cubemapDisplay, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayouts.scene, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.offscreen, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - // Uniform buffers - uniformBuffers.offscreen.destroy(); - uniformBuffers.scene.destroy(); - } - } - - void prepareCubeMap() - { - shadowCubeMap.width = offscreenImageSize; - shadowCubeMap.height = offscreenImageSize; - - // Cube map image description - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = offscreenImageFormat; - imageCreateInfo.extent = { shadowCubeMap.width, shadowCubeMap.height, 1 }; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 6; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // Create cube map image - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &shadowCubeMap.image)); - - vkGetImageMemoryRequirements(device, shadowCubeMap.image, &memReqs); - - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &shadowCubeMap.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, shadowCubeMap.image, shadowCubeMap.deviceMemory, 0)); - - // Image barrier for optimal image (target) - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = 1; - subresourceRange.layerCount = 6; - vks::tools::setImageLayout( - layoutCmd, - shadowCubeMap.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - subresourceRange); - - vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); - - // Create sampler - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 1.0f; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = 1.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &shadowCubeMap.sampler)); - - // Create image view - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.image = VK_NULL_HANDLE; - view.viewType = VK_IMAGE_VIEW_TYPE_CUBE; - view.format = offscreenImageFormat; - view.components = { VK_COMPONENT_SWIZZLE_R }; - view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - view.subresourceRange.layerCount = 6; - view.image = shadowCubeMap.image; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &shadowCubeMap.view)); - - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.subresourceRange.layerCount = 1; - view.image = shadowCubeMap.image; - - for (uint32_t i = 0; i < 6; i++) - { - view.subresourceRange.baseArrayLayer = i; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &shadowCubeMapFaceImageViews[i])); - } - } - - // Set up a separate render pass for the offscreen frame buffer - // This is necessary as the offscreen frame buffer attachments - // use formats different to the ones from the visible frame buffer - // and at least the depth one may not be compatible - void prepareOffscreenRenderpass() - { - VkAttachmentDescription osAttachments[2] = {}; - - // Find a suitable depth format for - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &offscreenDepthFormat); - assert(validDepthFormat); - - osAttachments[0].format = offscreenImageFormat; - osAttachments[0].samples = VK_SAMPLE_COUNT_1_BIT; - osAttachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - osAttachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - osAttachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - osAttachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - osAttachments[0].initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - osAttachments[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - // Depth attachment - osAttachments[1].format = offscreenDepthFormat; - osAttachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - osAttachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - osAttachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - osAttachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - osAttachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - osAttachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - osAttachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorReference = {}; - colorReference.attachment = 0; - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthReference = {}; - depthReference.attachment = 1; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorReference; - subpass.pDepthStencilAttachment = &depthReference; - - VkRenderPassCreateInfo renderPassCreateInfo = vks::initializers::renderPassCreateInfo(); - renderPassCreateInfo.attachmentCount = 2; - renderPassCreateInfo.pAttachments = osAttachments; - renderPassCreateInfo.subpassCount = 1; - renderPassCreateInfo.pSubpasses = &subpass; - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, &offscreenPass.renderPass)); - } - - // Prepare a new framebuffer for offscreen rendering - // The contents of this framebuffer are then - // copied to the different cube map faces - void prepareOffscreenFramebuffer() - { - offscreenPass.width = offscreenImageSize; - offscreenPass.height = offscreenImageSize; - - // Color attachment - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = offscreenImageFormat; - imageCreateInfo.extent.width = offscreenPass.width; - imageCreateInfo.extent.height = offscreenPass.height; - imageCreateInfo.extent.depth = 1; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - // Image of the framebuffer is blit source - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = offscreenImageFormat; - colorImageView.flags = 0; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - - VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // Depth stencil attachment - imageCreateInfo.format = offscreenDepthFormat; - imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - - VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo(); - depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilView.format = offscreenDepthFormat; - depthStencilView.flags = 0; - depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (offscreenDepthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) { - depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - depthStencilView.subresourceRange.baseMipLevel = 0; - depthStencilView.subresourceRange.levelCount = 1; - depthStencilView.subresourceRange.baseArrayLayer = 0; - depthStencilView.subresourceRange.layerCount = 1; - - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreenPass.depth.image)); - - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs); - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0)); - - vks::tools::setImageLayout( - layoutCmd, - offscreenPass.depth.image, - VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - - vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); - - depthStencilView.image = offscreenPass.depth.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view)); - - VkImageView attachments[2]; - attachments[1] = offscreenPass.depth.view; - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = offscreenPass.renderPass; - fbufCreateInfo.attachmentCount = 2; - fbufCreateInfo.pAttachments = attachments; - fbufCreateInfo.width = offscreenPass.width; - fbufCreateInfo.height = offscreenPass.height; - fbufCreateInfo.layers = 1; - - for (uint32_t i = 0; i < 6; i++) - { - attachments[0] = shadowCubeMapFaceImageViews[i]; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreenPass.frameBuffers[i])); - } - } - - // Updates a single cube map face - // Renders the scene with face's view directly to the cubemap layer `faceIndex` - // Uses push constants for quick update of view matrix for the current cube map face - void updateCubeFace(uint32_t faceIndex, VkCommandBuffer commandBuffer) - { - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - // Reuse render pass from example pass - renderPassBeginInfo.renderPass = offscreenPass.renderPass; - renderPassBeginInfo.framebuffer = offscreenPass.frameBuffers[faceIndex]; - renderPassBeginInfo.renderArea.extent.width = offscreenPass.width; - renderPassBeginInfo.renderArea.extent.height = offscreenPass.height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - // Update view matrix via push constant - - glm::mat4 viewMatrix = glm::mat4(1.0f); - switch (faceIndex) - { - case 0: // POSITIVE_X - viewMatrix = glm::rotate(viewMatrix, glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f)); - viewMatrix = glm::rotate(viewMatrix, glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)); - break; - case 1: // NEGATIVE_X - viewMatrix = glm::rotate(viewMatrix, glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)); - viewMatrix = glm::rotate(viewMatrix, glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)); - break; - case 2: // POSITIVE_Y - viewMatrix = glm::rotate(viewMatrix, glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); - break; - case 3: // NEGATIVE_Y - viewMatrix = glm::rotate(viewMatrix, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); - break; - case 4: // POSITIVE_Z - viewMatrix = glm::rotate(viewMatrix, glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)); - break; - case 5: // NEGATIVE_Z - viewMatrix = glm::rotate(viewMatrix, glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)); - break; - } - - // Render scene from cube face's point of view - vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - // Update shader push constant block - // Contains current face view matrix - vkCmdPushConstants( - commandBuffer, - pipelineLayouts.offscreen, - VK_SHADER_STAGE_VERTEX_BIT, - 0, - sizeof(glm::mat4), - &viewMatrix); - - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.offscreen); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.offscreen, 0, 1, &descriptorSets.offscreen, 0, NULL); - models.scene.draw(commandBuffer); - - vkCmdEndRenderPass(commandBuffer); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Generate shadow cube maps using one render pass per face - */ - { - VkViewport viewport = vks::initializers::viewport((float)offscreenPass.width, (float)offscreenPass.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(offscreenPass.width, offscreenPass.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - for (uint32_t face = 0; face < 6; face++) { - updateCubeFace(face, drawCmdBuffers[i]); - } - } - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Scene rendering with applied shadow map - */ - { - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = frameBuffers[i]; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, NULL); - - if (displayCubeMap) - { - // Display all six sides of the shadow cube map - // Note: Visualization of the different faces is done in the fragment shader, see cubemapdisplay.frag - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.cubemapDisplay); - models.debugcube.draw(drawCmdBuffers[i]); - } - else - { - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.scene); - models.scene.draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.debugcube.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.scene.loadFromFile(getAssetPath() + "models/shadowscene_fire.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader image sampler (cube map) - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - // 3D scene - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.scene)); - // Image descriptor for the cube map - VkDescriptorImageInfo texDescriptor = - vks::initializers::descriptorImageInfo( - shadowCubeMap.sampler, - shadowCubeMap.view, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - std::vector sceneDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor), - // Binding 1 : Fragment shader shadow sampler - vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &texDescriptor) - }; - vkUpdateDescriptorSets(device, static_cast(sceneDescriptorSets.size()), sceneDescriptorSets.data(), 0, nullptr); - - // Offscreen - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.offscreen)); - std::vector offScreenWriteDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.offscreen, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.offscreen.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(offScreenWriteDescriptorSets.size()), offScreenWriteDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layouts - // 3D scene pipeline layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.scene)); - - // Offscreen pipeline layout - // Push constants for cube map face view matrices - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); - // Push constant ranges are part of the pipeline layout - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.offscreen)); - - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - // 3D scene pipeline - // Load shaders - std::array shaderStages; - - shaderStages[0] = loadShader(getShadersPath() + "shadowmappingomni/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "shadowmappingomni/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.scene, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal}); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.scene)); - - // Offscreen pipeline - shaderStages[0] = loadShader(getShadersPath() + "shadowmappingomni/offscreen.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "shadowmappingomni/offscreen.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - pipelineCI.layout = pipelineLayouts.offscreen; - pipelineCI.renderPass = offscreenPass.renderPass; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.offscreen)); - - // Cube map display pipeline - shaderStages[0] = loadShader(getShadersPath() + "shadowmappingomni/cubemapdisplay.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "shadowmappingomni/cubemapdisplay.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCI.pVertexInputState = &emptyInputState; - pipelineCI.layout = pipelineLayouts.scene; - pipelineCI.renderPass = renderPass; - rasterizationState.cullMode = VK_CULL_MODE_NONE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.cubemapDisplay)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Offscreen vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.offscreen, sizeof(UniformData))); - // Scene vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.scene, sizeof(UniformData))); - // Map persistent - VK_CHECK_RESULT(uniformBuffers.offscreen.map()); - VK_CHECK_RESULT(uniformBuffers.scene.map()); - } - - void updateUniformBuffers() - { - uniformDataScene.projection = camera.matrices.perspective; - uniformDataScene.view = camera.matrices.view; - uniformDataScene.model = glm::mat4(1.0f); - uniformDataScene.lightPos = lightPos; - memcpy(uniformBuffers.scene.mapped, &uniformDataScene, sizeof(UniformData)); - } - - void updateUniformBufferOffscreen() - { - lightPos.x = sin(glm::radians(timer * 360.0f)) * 0.15f; - lightPos.z = cos(glm::radians(timer * 360.0f)) * 0.15f; - uniformDataOffscreen.projection = glm::perspective((float)(M_PI / 2.0), 1.0f, zNear, zFar); - uniformDataOffscreen.view = glm::mat4(1.0f); - uniformDataOffscreen.model = glm::translate(glm::mat4(1.0f), glm::vec3(-lightPos.x, -lightPos.y, -lightPos.z)); - uniformDataOffscreen.lightPos = lightPos; - memcpy(uniformBuffers.offscreen.mapped, &uniformDataOffscreen, sizeof(UniformData)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - prepareCubeMap(); - setupDescriptors(); - prepareOffscreenRenderpass(); - preparePipelines(); - prepareOffscreenFramebuffer(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - updateUniformBufferOffscreen(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->checkBox("Display shadow cube render target", &displayCubeMap)) { - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/specializationconstants/specializationconstants.cpp b/examples/specializationconstants/specializationconstants.cpp deleted file mode 100644 index db357981..00000000 --- a/examples/specializationconstants/specializationconstants.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* -* Vulkan Example - Shader specialization constants -* -* This samples uses specialization constants to define shader constants at pipeline creation -* These are used to compile shaders with different execution paths and settings -* With these constants one can create different shader configurations from a single shader file -* See uber.frag for how such a shader can look -* -* For details see https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample: public VulkanExampleBase -{ -public: - vkglTF::Model scene; - vks::Texture2D colormap; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 lightPos{ 0.0f, -2.0f, 1.0f, 0.0f }; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - struct Pipelines{ - VkPipeline phong{ VK_NULL_HANDLE }; - VkPipeline toon{ VK_NULL_HANDLE }; - VkPipeline textured{ VK_NULL_HANDLE }; - } pipelines; - - VulkanExample() : VulkanExampleBase() - { - title = "Specialization constants"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, ((float)width / 3.0f) / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(-40.0f, -90.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -2.0f)); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.phong, nullptr); - vkDestroyPipeline(device, pipelines.textured, nullptr); - vkDestroyPipeline(device, pipelines.toon, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - colormap.destroy(); - uniformBuffer.destroy(); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - // Left - VkViewport viewport = vks::initializers::viewport((float) width / 3.0f, (float) height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phong); - scene.draw(drawCmdBuffers[i]); - - // Center - viewport.x = (float)width / 3.0f; - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.toon); - scene.draw(drawCmdBuffers[i]); - - // Right - viewport.x = (float)width / 3.0f + (float)width / 3.0f; - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.textured); - scene.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - scene.loadFromFile(getAssetPath() + "models/color_teapot_spheres.gltf", vulkanDevice, queue , vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY); - colormap.loadFromFile(getAssetPath() + "textures/metalplate_nomips_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &colormap.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color }); - - // Prepare specialization constants data - - // Host data to take specialization constants from - struct SpecializationData { - // Sets the lighting model used in the fragment "uber" shader - uint32_t lightingModel{ 0 }; - // Parameter for the toon shading part of the fragment shader - float toonDesaturationFactor{ 0.5f }; - } specializationData; - - // Each shader constant of a shader stage corresponds to one map entry - std::array specializationMapEntries; - // Shader bindings based on specialization constants are marked by the new "constant_id" layout qualifier: - // layout (constant_id = 0) const int LIGHTING_MODEL = 0; - // layout (constant_id = 1) const float PARAM_TOON_DESATURATION = 0.0f; - - // Map entry for the lighting model to be used by the fragment shader - specializationMapEntries[0].constantID = 0; - specializationMapEntries[0].size = sizeof(specializationData.lightingModel); - specializationMapEntries[0].offset = 0; - - // Map entry for the toon shader parameter - specializationMapEntries[1].constantID = 1; - specializationMapEntries[1].size = sizeof(specializationData.toonDesaturationFactor); - specializationMapEntries[1].offset = offsetof(SpecializationData, toonDesaturationFactor); - - // Prepare specialization info block for the shader stage - VkSpecializationInfo specializationInfo{}; - specializationInfo.dataSize = sizeof(specializationData); - specializationInfo.mapEntryCount = static_cast(specializationMapEntries.size()); - specializationInfo.pMapEntries = specializationMapEntries.data(); - specializationInfo.pData = &specializationData; - - // Create pipelines - // All pipelines will use the same "uber" shader and specialization constants to change branching and parameters of that shader - shaderStages[0] = loadShader(getShadersPath() + "specializationconstants/uber.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "specializationconstants/uber.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Specialization info is assigned is part of the shader stage (modul) and must be set after creating the module and before creating the pipeline - shaderStages[1].pSpecializationInfo = &specializationInfo; - - // Solid phong shading - specializationData.lightingModel = 0; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.phong)); - - // Phong and textured - specializationData.lightingModel = 1; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.toon)); - - // Textured discard - specializationData.lightingModel = 2; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.textured)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Create the vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - camera.setPerspective(60.0f, ((float)width / 3.0f) / (float)height, 0.1f, 512.0f); - - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) { - return; - } - updateUniformBuffers(); - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/sphericalenvmapping/sphericalenvmapping.cpp b/examples/sphericalenvmapping/sphericalenvmapping.cpp deleted file mode 100644 index a4f3b3e6..00000000 --- a/examples/sphericalenvmapping/sphericalenvmapping.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* -* Vulkan Example - Spherical Environment Mapping, using different mat caps stored in an array texture -* -* Use +/-/space toggle through different material captures -* -* Based on https://www.clicktorelease.com/blog/creating-spherical-environment-mapping-shader -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - vkglTF::Model model; - vks::Texture2DArray matCapTextureArray; - - struct UniformData { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 normal; - glm::mat4 view; - // Selects the texture index of the material to display (see sem.vert) - int32_t texIndex = 0; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Spherical Environment Mapping"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -3.5f)); - camera.setRotation(glm::vec3(-25.0f, 23.75f, 0.0f)); - camera.setRotationSpeed(0.75f); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - matCapTextureArray.destroy(); - } - } - - void loadAssets() - { - model.loadFromFile(getAssetPath() + "models/chinesedragon.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY); - // Multiple mat caps are stored in a single array texture so they can easily be switched inside the shader just by updating the index in a uniform buffer - matCapTextureArray.loadFromFile(getAssetPath() + "textures/matcap_array_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - model.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader color map image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Fragment shader image sampler - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &matCapTextureArray.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); - - // Spherical environment rendering pipeline - shaderStages[0] = loadShader(getShadersPath() + "sphericalenvmapping/sem.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "sphericalenvmapping/sem.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.model = glm::mat4(1.0f); - uniformData.normal = glm::inverseTranspose(uniformData.view * uniformData.model); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->sliderInt("Material cap", &uniformData.texIndex, 0, matCapTextureArray.layerCount); - } - } - -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/ssao/ssao.cpp b/examples/ssao/ssao.cpp deleted file mode 100644 index 76e84953..00000000 --- a/examples/ssao/ssao.cpp +++ /dev/null @@ -1,953 +0,0 @@ -/* -* Vulkan Example - Screen space ambient occlusion example -* -* Copyright (C) by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -#define SSAO_KERNEL_SIZE 64 -#define SSAO_RADIUS 0.3f - -// We use a smaller noise kernel size on Android due to lower computational power -#if defined(__ANDROID__) -#define SSAO_NOISE_DIM 4 -#else -#define SSAO_NOISE_DIM 8 -#endif - -class VulkanExample : public VulkanExampleBase -{ -public: - vks::Texture2D ssaoNoise; - vkglTF::Model scene; - - struct UBOSceneParams { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - float nearPlane = 0.1f; - float farPlane = 64.0f; - } uboSceneParams; - - struct UBOSSAOParams { - glm::mat4 projection; - int32_t ssao = true; - int32_t ssaoOnly = false; - int32_t ssaoBlur = true; - } uboSSAOParams; - - struct { - VkPipeline offscreen{ VK_NULL_HANDLE }; - VkPipeline composition{ VK_NULL_HANDLE }; - VkPipeline ssao{ VK_NULL_HANDLE }; - VkPipeline ssaoBlur{ VK_NULL_HANDLE }; - } pipelines; - - struct { - VkPipelineLayout gBuffer{ VK_NULL_HANDLE }; - VkPipelineLayout ssao{ VK_NULL_HANDLE }; - VkPipelineLayout ssaoBlur{ VK_NULL_HANDLE }; - VkPipelineLayout composition{ VK_NULL_HANDLE }; - } pipelineLayouts; - - struct { - VkDescriptorSet gBuffer{ VK_NULL_HANDLE }; - VkDescriptorSet ssao{ VK_NULL_HANDLE }; - VkDescriptorSet ssaoBlur{ VK_NULL_HANDLE }; - VkDescriptorSet composition{ VK_NULL_HANDLE }; - const uint32_t count = 4; - } descriptorSets; - - struct { - VkDescriptorSetLayout gBuffer{ VK_NULL_HANDLE }; - VkDescriptorSetLayout ssao{ VK_NULL_HANDLE }; - VkDescriptorSetLayout ssaoBlur{ VK_NULL_HANDLE }; - VkDescriptorSetLayout composition{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - struct { - vks::Buffer sceneParams; - vks::Buffer ssaoKernel; - vks::Buffer ssaoParams; - } uniformBuffers; - - // Framebuffer for offscreen rendering - struct FrameBufferAttachment { - VkImage image; - VkDeviceMemory mem; - VkImageView view; - VkFormat format; - void destroy(VkDevice device) - { - vkDestroyImage(device, image, nullptr); - vkDestroyImageView(device, view, nullptr); - vkFreeMemory(device, mem, nullptr); - } - }; - struct FrameBuffer { - int32_t width, height; - VkFramebuffer frameBuffer; - VkRenderPass renderPass; - void setSize(int32_t w, int32_t h) - { - this->width = w; - this->height = h; - } - void destroy(VkDevice device) - { - vkDestroyFramebuffer(device, frameBuffer, nullptr); - vkDestroyRenderPass(device, renderPass, nullptr); - } - }; - - struct { - struct Offscreen : public FrameBuffer { - FrameBufferAttachment position, normal, albedo, depth; - } offscreen; - struct SSAO : public FrameBuffer { - FrameBufferAttachment color; - } ssao, ssaoBlur; - } frameBuffers{}; - - // One sampler for the frame buffer color attachments - VkSampler colorSampler; - - VulkanExample() : VulkanExampleBase() - { - title = "Screen space ambient occlusion"; - camera.type = Camera::CameraType::firstperson; -#ifndef __ANDROID__ - camera.rotationSpeed = 0.25f; -#endif - camera.position = { 1.0f, 0.75f, 0.0f }; - camera.setRotation(glm::vec3(0.0f, 90.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, uboSceneParams.nearPlane, uboSceneParams.farPlane); - } - - ~VulkanExample() - { - if (device) { - vkDestroySampler(device, colorSampler, nullptr); - - // Attachments - frameBuffers.offscreen.position.destroy(device); - frameBuffers.offscreen.normal.destroy(device); - frameBuffers.offscreen.albedo.destroy(device); - frameBuffers.offscreen.depth.destroy(device); - frameBuffers.ssao.color.destroy(device); - frameBuffers.ssaoBlur.color.destroy(device); - - // Framebuffers - frameBuffers.offscreen.destroy(device); - frameBuffers.ssao.destroy(device); - frameBuffers.ssaoBlur.destroy(device); - - vkDestroyPipeline(device, pipelines.offscreen, nullptr); - vkDestroyPipeline(device, pipelines.composition, nullptr); - vkDestroyPipeline(device, pipelines.ssao, nullptr); - vkDestroyPipeline(device, pipelines.ssaoBlur, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayouts.gBuffer, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.ssao, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.ssaoBlur, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.composition, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.gBuffer, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.ssao, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.ssaoBlur, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.composition, nullptr); - - // Uniform buffers - uniformBuffers.sceneParams.destroy(); - uniformBuffers.ssaoKernel.destroy(); - uniformBuffers.ssaoParams.destroy(); - - ssaoNoise.destroy(); - } - } - - void getEnabledFeatures() - { - enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy; - } - - // Create a frame buffer attachment - void createAttachment( - VkFormat format, - VkImageUsageFlagBits usage, - FrameBufferAttachment *attachment, - uint32_t width, - uint32_t height) - { - VkImageAspectFlags aspectMask = 0; - - attachment->format = format; - - if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) - { - aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - } - if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) - { - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (format >= VK_FORMAT_D16_UNORM_S8_UINT) - aspectMask |=VK_IMAGE_ASPECT_STENCIL_BIT; - } - - assert(aspectMask > 0); - - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = format; - image.extent.width = width; - image.extent.height = height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.usage = usage | VK_IMAGE_USAGE_SAMPLED_BIT; - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &attachment->image)); - vkGetImageMemoryRequirements(device, attachment->image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &attachment->mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, attachment->image, attachment->mem, 0)); - - VkImageViewCreateInfo imageView = vks::initializers::imageViewCreateInfo(); - imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageView.format = format; - imageView.subresourceRange = {}; - imageView.subresourceRange.aspectMask = aspectMask; - imageView.subresourceRange.baseMipLevel = 0; - imageView.subresourceRange.levelCount = 1; - imageView.subresourceRange.baseArrayLayer = 0; - imageView.subresourceRange.layerCount = 1; - imageView.image = attachment->image; - VK_CHECK_RESULT(vkCreateImageView(device, &imageView, nullptr, &attachment->view)); - } - - void prepareOffscreenFramebuffers() - { - // Attachments -#if defined(__ANDROID__) - const uint32_t ssaoWidth = width / 2; - const uint32_t ssaoHeight = height / 2; -#else - const uint32_t ssaoWidth = width; - const uint32_t ssaoHeight = height; -#endif - - frameBuffers.offscreen.setSize(width, height); - frameBuffers.ssao.setSize(ssaoWidth, ssaoHeight); - frameBuffers.ssaoBlur.setSize(width, height); - - // Find a suitable depth format - VkFormat attDepthFormat; - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attDepthFormat); - assert(validDepthFormat); - - // G-Buffer - createAttachment(VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &frameBuffers.offscreen.position, width, height); // Position + Depth - createAttachment(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &frameBuffers.offscreen.normal, width, height); // Normals - createAttachment(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &frameBuffers.offscreen.albedo, width, height); // Albedo (color) - createAttachment(attDepthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &frameBuffers.offscreen.depth, width, height); // Depth - - // SSAO - createAttachment(VK_FORMAT_R8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &frameBuffers.ssao.color, ssaoWidth, ssaoHeight); // Color - - // SSAO blur - createAttachment(VK_FORMAT_R8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &frameBuffers.ssaoBlur.color, width, height); // Color - - // Render passes - - // G-Buffer creation - { - std::array attachmentDescs = {}; - - // Init attachment properties - for (uint32_t i = 0; i < static_cast(attachmentDescs.size()); i++) - { - attachmentDescs[i].samples = VK_SAMPLE_COUNT_1_BIT; - attachmentDescs[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachmentDescs[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachmentDescs[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachmentDescs[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachmentDescs[i].finalLayout = (i == 3) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - // Formats - attachmentDescs[0].format = frameBuffers.offscreen.position.format; - attachmentDescs[1].format = frameBuffers.offscreen.normal.format; - attachmentDescs[2].format = frameBuffers.offscreen.albedo.format; - attachmentDescs[3].format = frameBuffers.offscreen.depth.format; - - std::vector colorReferences; - colorReferences.push_back({ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); - colorReferences.push_back({ 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); - colorReferences.push_back({ 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }); - - VkAttachmentReference depthReference = {}; - depthReference.attachment = 3; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.pColorAttachments = colorReferences.data(); - subpass.colorAttachmentCount = static_cast(colorReferences.size()); - subpass.pDepthStencilAttachment = &depthReference; - - // Use subpass dependencies for attachment layout transitions - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.pAttachments = attachmentDescs.data(); - renderPassInfo.attachmentCount = static_cast(attachmentDescs.size()); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 2; - renderPassInfo.pDependencies = dependencies.data(); - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &frameBuffers.offscreen.renderPass)); - - std::array attachments; - attachments[0] = frameBuffers.offscreen.position.view; - attachments[1] = frameBuffers.offscreen.normal.view; - attachments[2] = frameBuffers.offscreen.albedo.view; - attachments[3] = frameBuffers.offscreen.depth.view; - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = frameBuffers.offscreen.renderPass; - fbufCreateInfo.pAttachments = attachments.data(); - fbufCreateInfo.attachmentCount = static_cast(attachments.size()); - fbufCreateInfo.width = frameBuffers.offscreen.width; - fbufCreateInfo.height = frameBuffers.offscreen.height; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &frameBuffers.offscreen.frameBuffer)); - } - - // SSAO - { - VkAttachmentDescription attachmentDescription{}; - attachmentDescription.format = frameBuffers.ssao.color.format; - attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; - attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachmentDescription.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.pColorAttachments = &colorReference; - subpass.colorAttachmentCount = 1; - - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.pAttachments = &attachmentDescription; - renderPassInfo.attachmentCount = 1; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 2; - renderPassInfo.pDependencies = dependencies.data(); - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &frameBuffers.ssao.renderPass)); - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = frameBuffers.ssao.renderPass; - fbufCreateInfo.pAttachments = &frameBuffers.ssao.color.view; - fbufCreateInfo.attachmentCount = 1; - fbufCreateInfo.width = frameBuffers.ssao.width; - fbufCreateInfo.height = frameBuffers.ssao.height; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &frameBuffers.ssao.frameBuffer)); - } - - // SSAO Blur - { - VkAttachmentDescription attachmentDescription{}; - attachmentDescription.format = frameBuffers.ssaoBlur.color.format; - attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; - attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachmentDescription.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.pColorAttachments = &colorReference; - subpass.colorAttachmentCount = 1; - - std::array dependencies; - - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.pAttachments = &attachmentDescription; - renderPassInfo.attachmentCount = 1; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 2; - renderPassInfo.pDependencies = dependencies.data(); - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &frameBuffers.ssaoBlur.renderPass)); - - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = frameBuffers.ssaoBlur.renderPass; - fbufCreateInfo.pAttachments = &frameBuffers.ssaoBlur.color.view; - fbufCreateInfo.attachmentCount = 1; - fbufCreateInfo.width = frameBuffers.ssaoBlur.width; - fbufCreateInfo.height = frameBuffers.ssaoBlur.height; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &frameBuffers.ssaoBlur.frameBuffer)); - } - - // Shared sampler used for all color attachments - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_NEAREST; - sampler.minFilter = VK_FILTER_NEAREST; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 1.0f; - sampler.minLod = 0.0f; - sampler.maxLod = 1.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &colorSampler)); - } - - void loadAssets() - { - vkglTF::descriptorBindingFlags = vkglTF::DescriptorBindingFlags::ImageBaseColor; - const uint32_t gltfLoadingFlags = vkglTF::FileLoadingFlags::FlipY | vkglTF::FileLoadingFlags::PreTransformVertices; - scene.loadFromFile(getAssetPath() + "models/sponza/sponza.gltf", vulkanDevice, queue, gltfLoadingFlags); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - /* - Offscreen SSAO generation - */ - { - // Clear values for all attachments written in the fragment shader - std::vector clearValues(4); - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - clearValues[1].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - clearValues[2].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - clearValues[3].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = frameBuffers.offscreen.renderPass; - renderPassBeginInfo.framebuffer = frameBuffers.offscreen.frameBuffer; - renderPassBeginInfo.renderArea.extent.width = frameBuffers.offscreen.width; - renderPassBeginInfo.renderArea.extent.height = frameBuffers.offscreen.height; - renderPassBeginInfo.clearValueCount = static_cast(clearValues.size()); - renderPassBeginInfo.pClearValues = clearValues.data(); - - /* - First pass: Fill G-Buffer components (positions+depth, normals, albedo) using MRT - */ - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)frameBuffers.offscreen.width, (float)frameBuffers.offscreen.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(frameBuffers.offscreen.width, frameBuffers.offscreen.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.offscreen); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.gBuffer, 0, 1, &descriptorSets.gBuffer, 0, nullptr); - scene.draw(drawCmdBuffers[i], vkglTF::RenderFlags::BindImages, pipelineLayouts.gBuffer); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - /* - Second pass: SSAO generation - */ - - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - renderPassBeginInfo.framebuffer = frameBuffers.ssao.frameBuffer; - renderPassBeginInfo.renderPass = frameBuffers.ssao.renderPass; - renderPassBeginInfo.renderArea.extent.width = frameBuffers.ssao.width; - renderPassBeginInfo.renderArea.extent.height = frameBuffers.ssao.height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues.data(); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - viewport = vks::initializers::viewport((float)frameBuffers.ssao.width, (float)frameBuffers.ssao.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - scissor = vks::initializers::rect2D(frameBuffers.ssao.width, frameBuffers.ssao.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.ssao, 0, 1, &descriptorSets.ssao, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.ssao); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - /* - Third pass: SSAO blur - */ - - renderPassBeginInfo.framebuffer = frameBuffers.ssaoBlur.frameBuffer; - renderPassBeginInfo.renderPass = frameBuffers.ssaoBlur.renderPass; - renderPassBeginInfo.renderArea.extent.width = frameBuffers.ssaoBlur.width; - renderPassBeginInfo.renderArea.extent.height = frameBuffers.ssaoBlur.height; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - viewport = vks::initializers::viewport((float)frameBuffers.ssaoBlur.width, (float)frameBuffers.ssaoBlur.height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - scissor = vks::initializers::rect2D(frameBuffers.ssaoBlur.width, frameBuffers.ssaoBlur.height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.ssaoBlur, 0, 1, &descriptorSets.ssaoBlur, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.ssaoBlur); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - /* - Note: Explicit synchronization is not required between the render pass, as this is done implicit via sub pass dependencies - */ - - /* - Final render pass: Scene rendering with applied radial blur - */ - { - std::vector clearValues(2); - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = VulkanExampleBase::frameBuffers[i]; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues.data(); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.composition, 0, 1, &descriptorSets.composition, 0, NULL); - - // Final composition pass - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.composition); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 10), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 12) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, descriptorSets.count); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - std::vector setLayoutBindings; - VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo; - VkDescriptorSetAllocateInfo descriptorAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, nullptr, 1); - std::vector writeDescriptorSets; - std::vector imageDescriptors; - - // Layouts and Sets - - // G-Buffer creation (offscreen scene rendering) - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), // VS + FS Parameter UBO - }; - setLayoutCreateInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &setLayoutCreateInfo, nullptr, &descriptorSetLayouts.gBuffer)); - - descriptorAllocInfo.pSetLayouts = &descriptorSetLayouts.gBuffer; - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocInfo, &descriptorSets.gBuffer)); - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.gBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.sceneParams.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // SSAO Generation - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), // FS Position+Depth - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), // FS Normals - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), // FS SSAO Noise - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), // FS SSAO Kernel UBO - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 4), // FS Params UBO - }; - setLayoutCreateInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &setLayoutCreateInfo, nullptr, &descriptorSetLayouts.ssao)); - - descriptorAllocInfo.pSetLayouts = &descriptorSetLayouts.ssao; - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocInfo, &descriptorSets.ssao)); - imageDescriptors = { - vks::initializers::descriptorImageInfo(colorSampler, frameBuffers.offscreen.position.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - vks::initializers::descriptorImageInfo(colorSampler, frameBuffers.offscreen.normal.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - }; - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.ssao, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageDescriptors[0]), // FS Position+Depth - vks::initializers::writeDescriptorSet(descriptorSets.ssao, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &imageDescriptors[1]), // FS Normals - vks::initializers::writeDescriptorSet(descriptorSets.ssao, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &ssaoNoise.descriptor), // FS SSAO Noise - vks::initializers::writeDescriptorSet(descriptorSets.ssao, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3, &uniformBuffers.ssaoKernel.descriptor), // FS SSAO Kernel UBO - vks::initializers::writeDescriptorSet(descriptorSets.ssao, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4, &uniformBuffers.ssaoParams.descriptor), // FS SSAO Params UBO - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // SSAO Blur - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), // FS Sampler SSAO - }; - setLayoutCreateInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &setLayoutCreateInfo, nullptr, &descriptorSetLayouts.ssaoBlur)); - descriptorAllocInfo.pSetLayouts = &descriptorSetLayouts.ssaoBlur; - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocInfo, &descriptorSets.ssaoBlur)); - imageDescriptors = { - vks::initializers::descriptorImageInfo(colorSampler, frameBuffers.ssao.color.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - }; - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.ssaoBlur, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageDescriptors[0]), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Composition - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), // FS Position+Depth - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), // FS Normals - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), // FS Albedo - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), // FS SSAO - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 4), // FS SSAO blurred - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 5), // FS Lights UBO - }; - setLayoutCreateInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &setLayoutCreateInfo, nullptr, &descriptorSetLayouts.composition)); - descriptorAllocInfo.pSetLayouts = &descriptorSetLayouts.composition; - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocInfo, &descriptorSets.composition)); - imageDescriptors = { - vks::initializers::descriptorImageInfo(colorSampler, frameBuffers.offscreen.position.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - vks::initializers::descriptorImageInfo(colorSampler, frameBuffers.offscreen.normal.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - vks::initializers::descriptorImageInfo(colorSampler, frameBuffers.offscreen.albedo.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - vks::initializers::descriptorImageInfo(colorSampler, frameBuffers.ssao.color.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - vks::initializers::descriptorImageInfo(colorSampler, frameBuffers.ssaoBlur.color.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - }; - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageDescriptors[0]), // FS Sampler Position+Depth - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &imageDescriptors[1]), // FS Sampler Normals - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &imageDescriptors[2]), // FS Sampler Albedo - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &imageDescriptors[3]), // FS Sampler SSAO - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4, &imageDescriptors[4]), // FS Sampler SSAO blurred - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 5, &uniformBuffers.ssaoParams.descriptor), // FS SSAO Params UBO - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layouts - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(); - - const std::vector setLayouts = { descriptorSetLayouts.gBuffer, vkglTF::descriptorSetLayoutImage }; - pipelineLayoutCreateInfo.pSetLayouts = setLayouts.data(); - pipelineLayoutCreateInfo.setLayoutCount = 2; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.gBuffer)); - - pipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayouts.ssao; - pipelineLayoutCreateInfo.setLayoutCount = 1; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.ssao)); - - pipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayouts.ssaoBlur; - pipelineLayoutCreateInfo.setLayoutCount = 1; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.ssaoBlur)); - - pipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayouts.composition; - pipelineLayoutCreateInfo.setLayoutCount = 1; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.composition)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo( pipelineLayouts.composition, renderPass, 0); - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - - // Empty vertex input state for fullscreen passes - VkPipelineVertexInputStateCreateInfo emptyVertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - pipelineCreateInfo.pVertexInputState = &emptyVertexInputState; - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - - // Final composition pipeline - shaderStages[0] = loadShader(getShadersPath() + "ssao/fullscreen.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "ssao/composition.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.composition)); - - // SSAO generation pipeline - pipelineCreateInfo.renderPass = frameBuffers.ssao.renderPass; - pipelineCreateInfo.layout = pipelineLayouts.ssao; - // SSAO Kernel size and radius are constant for this pipeline, so we set them using specialization constants - struct SpecializationData { - uint32_t kernelSize = SSAO_KERNEL_SIZE; - float radius = SSAO_RADIUS; - } specializationData; - std::array specializationMapEntries = { - vks::initializers::specializationMapEntry(0, offsetof(SpecializationData, kernelSize), sizeof(SpecializationData::kernelSize)), - vks::initializers::specializationMapEntry(1, offsetof(SpecializationData, radius), sizeof(SpecializationData::radius)) - }; - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(2, specializationMapEntries.data(), sizeof(specializationData), &specializationData); - shaderStages[1] = loadShader(getShadersPath() + "ssao/ssao.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - shaderStages[1].pSpecializationInfo = &specializationInfo; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.ssao)); - - // SSAO blur pipeline - pipelineCreateInfo.renderPass = frameBuffers.ssaoBlur.renderPass; - pipelineCreateInfo.layout = pipelineLayouts.ssaoBlur; - shaderStages[1] = loadShader(getShadersPath() + "ssao/blur.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.ssaoBlur)); - - // Fill G-Buffer pipeline - // Vertex input state from glTF model loader - pipelineCreateInfo.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal }); - pipelineCreateInfo.renderPass = frameBuffers.offscreen.renderPass; - pipelineCreateInfo.layout = pipelineLayouts.gBuffer; - // Blend attachment states required for all color attachments - // This is important, as color write mask will otherwise be 0x0 and you - // won't see anything rendered to the attachment - std::array blendAttachmentStates = { - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE) - }; - colorBlendState.attachmentCount = static_cast(blendAttachmentStates.size()); - colorBlendState.pAttachments = blendAttachmentStates.data(); - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - shaderStages[0] = loadShader(getShadersPath() + "ssao/gbuffer.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "ssao/gbuffer.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.offscreen)); - } - - float lerp(float a, float b, float f) - { - return a + f * (b - a); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Scene matrices - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.sceneParams, - sizeof(uboSceneParams)); - - // SSAO parameters - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.ssaoParams, - sizeof(uboSSAOParams)); - - // Update - updateUniformBufferMatrices(); - updateUniformBufferSSAOParams(); - - // SSAO - std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::uniform_real_distribution rndDist(0.0f, 1.0f); - - // Sample kernel - std::vector ssaoKernel(SSAO_KERNEL_SIZE); - for (uint32_t i = 0; i < SSAO_KERNEL_SIZE; ++i) - { - glm::vec3 sample(rndDist(rndEngine) * 2.0 - 1.0, rndDist(rndEngine) * 2.0 - 1.0, rndDist(rndEngine)); - sample = glm::normalize(sample); - sample *= rndDist(rndEngine); - float scale = float(i) / float(SSAO_KERNEL_SIZE); - scale = lerp(0.1f, 1.0f, scale * scale); - ssaoKernel[i] = glm::vec4(sample * scale, 0.0f); - } - - // Upload as UBO - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.ssaoKernel, - ssaoKernel.size() * sizeof(glm::vec4), - ssaoKernel.data()); - - // Random noise - std::vector noiseValues(SSAO_NOISE_DIM * SSAO_NOISE_DIM); - for (uint32_t i = 0; i < static_cast(noiseValues.size()); i++) { - noiseValues[i] = glm::vec4(rndDist(rndEngine) * 2.0f - 1.0f, rndDist(rndEngine) * 2.0f - 1.0f, 0.0f, 0.0f); - } - // Upload as texture - ssaoNoise.fromBuffer(noiseValues.data(), noiseValues.size() * sizeof(glm::vec4), VK_FORMAT_R32G32B32A32_SFLOAT, SSAO_NOISE_DIM, SSAO_NOISE_DIM, vulkanDevice, queue, VK_FILTER_NEAREST); - } - - void updateUniformBufferMatrices() - { - uboSceneParams.projection = camera.matrices.perspective; - uboSceneParams.view = camera.matrices.view; - uboSceneParams.model = glm::mat4(1.0f); - - VK_CHECK_RESULT(uniformBuffers.sceneParams.map()); - uniformBuffers.sceneParams.copyTo(&uboSceneParams, sizeof(uboSceneParams)); - uniformBuffers.sceneParams.unmap(); - } - - void updateUniformBufferSSAOParams() - { - uboSSAOParams.projection = camera.matrices.perspective; - - VK_CHECK_RESULT(uniformBuffers.ssaoParams.map()); - uniformBuffers.ssaoParams.copyTo(&uboSSAOParams, sizeof(uboSSAOParams)); - uniformBuffers.ssaoParams.unmap(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareOffscreenFramebuffers(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) { - return; - } - updateUniformBufferMatrices(); - updateUniformBufferSSAOParams(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->checkBox("Enable SSAO", &uboSSAOParams.ssao); - overlay->checkBox("SSAO blur", &uboSSAOParams.ssaoBlur); - overlay->checkBox("SSAO pass only", &uboSSAOParams.ssaoOnly); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/stencilbuffer/stencilbuffer.cpp b/examples/stencilbuffer/stencilbuffer.cpp deleted file mode 100644 index 68b6c08a..00000000 --- a/examples/stencilbuffer/stencilbuffer.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* -* Vulkan Example - Rendering outlines using the stencil buffer -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - vkglTF::Model model; - - struct UniformData { - glm::mat4 projection; - glm::mat4 model; - glm::vec4 lightPos = glm::vec4(0.0f, -2.0f, 1.0f, 0.0f); - // Vertex shader extrudes model by this value along normals for outlining - float outlineWidth = 0.025f; - } uniformData; - vks::Buffer uniformBuffer; - - struct { - VkPipeline stencil{ VK_NULL_HANDLE }; - VkPipeline outline{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Stencil buffer outlines"; - timerSpeed *= 0.25f; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(2.5f, -35.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -2.0f)); - // This samples requires a format that supports depth AND stencil, which will be handled by the base class - requiresStencil = true; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.stencil, nullptr); - vkDestroyPipeline(device, pipelines.outline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - VkDeviceSize offsets[1] = { 0 }; - - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &model.vertices.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], model.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - // First pass renders object (toon shaded) and fills stencil buffer - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.stencil); - model.draw(drawCmdBuffers[i]); - - // Second pass renders scaled object only where stencil was not set by first pass - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.outline); - model.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - model.loadFromFile(getAssetPath() + "models/venus.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - - VkDescriptorSetLayoutCreateInfo descriptorLayoutInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), 1); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutInfo, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector modelWriteDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(modelWriteDescriptorSets.size()), modelWriteDescriptorSets.data(), 0, NULL); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_FRONT_BIT, VK_FRONT_FACE_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal }); - - // Toon render and stencil fill pass - shaderStages[0] = loadShader(getShadersPath() + "stencilbuffer/toon.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "stencilbuffer/toon.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - rasterizationState.cullMode = VK_CULL_MODE_NONE; - depthStencilState.stencilTestEnable = VK_TRUE; - depthStencilState.back.compareOp = VK_COMPARE_OP_ALWAYS; - depthStencilState.back.failOp = VK_STENCIL_OP_REPLACE; - depthStencilState.back.depthFailOp = VK_STENCIL_OP_REPLACE; - depthStencilState.back.passOp = VK_STENCIL_OP_REPLACE; - depthStencilState.back.compareMask = 0xff; - depthStencilState.back.writeMask = 0xff; - depthStencilState.back.reference = 1; - depthStencilState.front = depthStencilState.back; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.stencil)); - // Outline pass - depthStencilState.back.compareOp = VK_COMPARE_OP_NOT_EQUAL; - depthStencilState.back.failOp = VK_STENCIL_OP_KEEP; - depthStencilState.back.depthFailOp = VK_STENCIL_OP_KEEP; - depthStencilState.back.passOp = VK_STENCIL_OP_REPLACE; - depthStencilState.front = depthStencilState.back; - depthStencilState.depthTestEnable = VK_FALSE; - shaderStages[0] = loadShader(getShadersPath() + "stencilbuffer/outline.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "stencilbuffer/outline.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.outline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Mesh vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData), &uniformData)); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.model = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->inputFloat("Outline width", &uniformData.outlineWidth, 0.01f, 2)) { - updateUniformBuffers(); - } - } - } - -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/subpasses/subpasses.cpp b/examples/subpasses/subpasses.cpp deleted file mode 100644 index e28d32d9..00000000 --- a/examples/subpasses/subpasses.cpp +++ /dev/null @@ -1,832 +0,0 @@ -/* - * Vulkan Example - Using subpasses for G-Buffer compositing - * - * Copyright (C) 2016-2024 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - * - * Summary: - * Implements a deferred rendering setup with a forward transparency pass using sub passes - * - * Sub passes allow reading from the previous framebuffer (in the same render pass) at - * the same pixel position. - * - * This is a feature that was especially designed for tile-based-renderers - * (mostly mobile GPUs) and is a new optimization feature in Vulkan for those GPU types. - * - */ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - struct { - vks::Texture2D glass; - } textures; - - struct { - vkglTF::Model scene; - vkglTF::Model transparent; - } models; - - struct { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 view; - } uboGBuffer; - - struct Light { - glm::vec4 position; - glm::vec3 color; - float radius; - }; - - std::array lights; - - struct { - vks::Buffer GBuffer; - vks::Buffer lights; - } buffers; - - struct { - VkPipeline offscreen; - VkPipeline composition; - VkPipeline transparent; - } pipelines; - - struct { - VkPipelineLayout offscreen; - VkPipelineLayout composition; - VkPipelineLayout transparent; - } pipelineLayouts; - - struct { - VkDescriptorSet scene; - VkDescriptorSet composition; - VkDescriptorSet transparent; - } descriptorSets; - - struct { - VkDescriptorSetLayout scene; - VkDescriptorSetLayout composition; - VkDescriptorSetLayout transparent; - } descriptorSetLayouts; - - // G-Buffer framebuffer attachments - struct FrameBufferAttachment { - VkImage image = VK_NULL_HANDLE; - VkDeviceMemory mem = VK_NULL_HANDLE; - VkImageView view = VK_NULL_HANDLE; - VkFormat format; - }; - struct Attachments { - FrameBufferAttachment position, normal, albedo; - int32_t width; - int32_t height; - } attachments; - - VulkanExample() : VulkanExampleBase() - { - title = "Subpasses"; - camera.type = Camera::CameraType::firstperson; - camera.movementSpeed = 5.0f; -#ifndef __ANDROID__ - camera.rotationSpeed = 0.25f; -#endif - camera.setPosition(glm::vec3(-3.2f, 1.0f, 5.9f)); - camera.setRotation(glm::vec3(0.5f, 210.05f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - ui.subpass = 2; - - enabledFeatures.fragmentStoresAndAtomics = VK_TRUE; - } - - ~VulkanExample() - { - // Clean up used Vulkan resources - // Note : Inherited destructor cleans up resources stored in base class - vkDestroyPipeline(device, pipelines.offscreen, nullptr); - vkDestroyPipeline(device, pipelines.composition, nullptr); - vkDestroyPipeline(device, pipelines.transparent, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayouts.offscreen, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.composition, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.transparent, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.scene, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.composition, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.transparent, nullptr); - - clearAttachment(&attachments.position); - clearAttachment(&attachments.normal); - clearAttachment(&attachments.albedo); - - textures.glass.destroy(); - buffers.GBuffer.destroy(); - buffers.lights.destroy(); - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - }; - - void clearAttachment(FrameBufferAttachment* attachment) - { - vkDestroyImageView(device, attachment->view, nullptr); - vkDestroyImage(device, attachment->image, nullptr); - vkFreeMemory(device, attachment->mem, nullptr); - } - - // Create a frame buffer attachment - void createAttachment(VkFormat format, VkImageUsageFlags usage, FrameBufferAttachment *attachment) - { - if (attachment->image != VK_NULL_HANDLE) { - clearAttachment(attachment); - } - - VkImageAspectFlags aspectMask = 0; - - attachment->format = format; - - if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) - { - aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - } - if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) - { - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - } - - assert(aspectMask > 0); - - VkImageCreateInfo image = vks::initializers::imageCreateInfo(); - image.imageType = VK_IMAGE_TYPE_2D; - image.format = format; - image.extent.width = attachments.width; - image.extent.height = attachments.height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - // VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT flag is required for input attachments - image.usage = usage | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; - image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &attachment->image)); - vkGetImageMemoryRequirements(device, attachment->image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &attachment->mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, attachment->image, attachment->mem, 0)); - - VkImageViewCreateInfo imageView = vks::initializers::imageViewCreateInfo(); - imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageView.format = format; - imageView.subresourceRange = {}; - imageView.subresourceRange.aspectMask = aspectMask; - imageView.subresourceRange.baseMipLevel = 0; - imageView.subresourceRange.levelCount = 1; - imageView.subresourceRange.baseArrayLayer = 0; - imageView.subresourceRange.layerCount = 1; - imageView.image = attachment->image; - VK_CHECK_RESULT(vkCreateImageView(device, &imageView, nullptr, &attachment->view)); - } - - // Create color attachments for the G-Buffer components - void createGBufferAttachments() - { - createAttachment(VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &attachments.position); // (World space) Positions - createAttachment(VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &attachments.normal); // (World space) Normals - createAttachment(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &attachments.albedo); // Albedo (color) - } - - // Override framebuffer setup from base class, will automatically be called upon setup and if a window is resized - void setupFrameBuffer() - { - // If the window is resized, all the framebuffers/attachments used in our composition passes need to be recreated - if (attachments.width != width || attachments.height != height) { - attachments.width = width; - attachments.height = height; - createGBufferAttachments(); - // Since the framebuffers/attachments are referred in the descriptor sets, these need to be updated too - // Composition pass - std::vector< VkDescriptorImageInfo> descriptorImageInfos = { - vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.position.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.normal.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.albedo.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), - }; - std::vector writeDescriptorSets; - for (size_t i = 0; i < descriptorImageInfos.size(); i++) { - writeDescriptorSets.push_back(vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, static_cast(i), &descriptorImageInfos[i])); - } - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - // Forward pass - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.transparent, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, &descriptorImageInfos[0]), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - VkImageView attachments[5]; - - VkFramebufferCreateInfo frameBufferCreateInfo = {}; - frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - frameBufferCreateInfo.renderPass = renderPass; - frameBufferCreateInfo.attachmentCount = 5; - frameBufferCreateInfo.pAttachments = attachments; - frameBufferCreateInfo.width = width; - frameBufferCreateInfo.height = height; - frameBufferCreateInfo.layers = 1; - - // Create frame buffers for every swap chain image - frameBuffers.resize(swapChain.images.size()); - for (uint32_t i = 0; i < frameBuffers.size(); i++) - { - attachments[0] = swapChain.imageViews[i]; - attachments[1] = this->attachments.position.view; - attachments[2] = this->attachments.normal.view; - attachments[3] = this->attachments.albedo.view; - attachments[4] = depthStencil.view; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCreateInfo, nullptr, &frameBuffers[i])); - } - } - - // Override render pass setup from base class - void setupRenderPass() - { - attachments.width = width; - attachments.height = height; - - createGBufferAttachments(); - - std::array attachments{}; - // Color attachment - attachments[0].format = swapChain.colorFormat; - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - // Deferred attachments - // Position - attachments[1].format = this->attachments.position.format; - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[1].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - // Normals - attachments[2].format = this->attachments.normal.format; - attachments[2].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[2].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - // Albedo - attachments[3].format = this->attachments.albedo.format; - attachments[3].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[3].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[3].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[3].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[3].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[3].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[3].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - // Depth attachment - attachments[4].format = depthFormat; - attachments[4].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[4].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[4].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[4].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[4].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[4].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[4].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - // Three subpasses - std::array subpassDescriptions{}; - - // First subpass: Fill G-Buffer components - // ---------------------------------------------------------------------------------------- - - VkAttachmentReference colorReferences[4]; - colorReferences[0] = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - colorReferences[1] = { 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - colorReferences[2] = { 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - colorReferences[3] = { 3, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - VkAttachmentReference depthReference = { 4, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; - - subpassDescriptions[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescriptions[0].colorAttachmentCount = 4; - subpassDescriptions[0].pColorAttachments = colorReferences; - subpassDescriptions[0].pDepthStencilAttachment = &depthReference; - - // Second subpass: Final composition (using G-Buffer components) - // ---------------------------------------------------------------------------------------- - - VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - VkAttachmentReference inputReferences[3]; - inputReferences[0] = { 1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; - inputReferences[1] = { 2, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; - inputReferences[2] = { 3, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; - - subpassDescriptions[1].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescriptions[1].colorAttachmentCount = 1; - subpassDescriptions[1].pColorAttachments = &colorReference; - subpassDescriptions[1].pDepthStencilAttachment = &depthReference; - // Use the color attachments filled in the first pass as input attachments - subpassDescriptions[1].inputAttachmentCount = 3; - subpassDescriptions[1].pInputAttachments = inputReferences; - - // Third subpass: Forward transparency - // ---------------------------------------------------------------------------------------- - colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - - inputReferences[0] = { 1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; - - subpassDescriptions[2].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescriptions[2].colorAttachmentCount = 1; - subpassDescriptions[2].pColorAttachments = &colorReference; - subpassDescriptions[2].pDepthStencilAttachment = &depthReference; - // Use the color/depth attachments filled in the first pass as input attachments - subpassDescriptions[2].inputAttachmentCount = 1; - subpassDescriptions[2].pInputAttachments = inputReferences; - - // Subpass dependencies for layout transitions - std::array dependencies; - - // This makes sure that writes to the depth image are done before we try to write to it again - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;; - dependencies[0].srcAccessMask = 0; - dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = 0; - - dependencies[1].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].dstSubpass = 0; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].srcAccessMask = 0; - dependencies[1].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dependencyFlags = 0; - - // This dependency transitions the input attachment from color attachment to input attachment read - dependencies[2].srcSubpass = 0; - dependencies[2].dstSubpass = 1; - dependencies[2].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[2].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[2].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[2].dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; - dependencies[2].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[3].srcSubpass = 1; - dependencies[3].dstSubpass = 2; - dependencies[3].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[3].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[3].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[3].dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; - dependencies[3].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[4].srcSubpass = 2; - dependencies[4].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[4].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[4].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[4].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[4].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[4].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attachments.size()); - renderPassInfo.pAttachments = attachments.data(); - renderPassInfo.subpassCount = static_cast(subpassDescriptions.size()); - renderPassInfo.pSubpasses = subpassDescriptions.data(); - renderPassInfo.dependencyCount = static_cast(dependencies.size()); - renderPassInfo.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass)); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[5]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[2].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[3].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[4].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 5; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // First sub pass - // Renders the components of the scene to the G-Buffer attachments - { - vks::debugutils::cmdBeginLabel(drawCmdBuffers[i], "Subpass 0: Deferred G-Buffer creation", { 1.0f, 0.78f, 0.05f, 1.0f }); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.offscreen); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.offscreen, 0, 1, &descriptorSets.scene, 0, NULL); - models.scene.draw(drawCmdBuffers[i]); - - vks::debugutils::cmdEndLabel(drawCmdBuffers[i]); - } - - // Second sub pass - // This subpass will use the G-Buffer components that have been filled in the first subpass as input attachment for the final compositing - { - vks::debugutils::cmdBeginLabel(drawCmdBuffers[i], "Subpass 1: Deferred composition", { 0.0f, 0.5f, 1.0f, 1.0f }); - - vkCmdNextSubpass(drawCmdBuffers[i], VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.composition); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.composition, 0, 1, &descriptorSets.composition, 0, NULL); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - - vks::debugutils::cmdEndLabel(drawCmdBuffers[i]); - } - - // Third subpass - // Render transparent geometry using a forward pass that compares against depth generated during G-Buffer fill - { - vks::debugutils::cmdBeginLabel(drawCmdBuffers[i], "Subpass 2: Forward transparency", { 0.5f, 0.76f, 0.34f, 1.0f }); - - vkCmdNextSubpass(drawCmdBuffers[i], VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.transparent); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.transparent, 0, 1, &descriptorSets.transparent, 0, NULL); - models.transparent.draw(drawCmdBuffers[i]); - - vks::debugutils::cmdEndLabel(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.scene.loadFromFile(getAssetPath() + "models/samplebuilding.gltf", vulkanDevice, queue, glTFLoadingFlags); - models.transparent.loadFromFile(getAssetPath() + "models/samplebuilding_glass.gltf", vulkanDevice, queue, glTFLoadingFlags); - textures.glass.loadFromFile(getAssetPath() + "textures/colored_glass_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 4), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo( static_cast(poolSizes.size()), poolSizes.data(), 4); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.scene)); - - // Sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.scene, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.scene)); - std::vector writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &buffers.GBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.scene, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.offscreen)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Final fullscreen pass pipeline - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.offscreen, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.subpass = 0; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV}); - - std::array blendAttachmentStates = { - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE), - vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE) - }; - - colorBlendState.attachmentCount = static_cast(blendAttachmentStates.size()); - colorBlendState.pAttachments = blendAttachmentStates.data(); - - // Offscreen scene rendering pipeline - shaderStages[0] = loadShader(getShadersPath() + "subpasses/gbuffer.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "subpasses/gbuffer.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.offscreen)); - } - - // Create the Vulkan objects used in the composition pass (descriptor sets, pipelines, etc.) - void prepareCompositionPass() - { - // Descriptor set layout - std::vector setLayoutBindings = - { - // Binding 0: Position input attachment - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // Binding 1: Normal input attachment - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 2: Albedo input attachment - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - // Binding 3: Light positions - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), - }; - - VkDescriptorSetLayoutCreateInfo descriptorLayout = - vks::initializers::descriptorSetLayoutCreateInfo( - setLayoutBindings.data(), - static_cast(setLayoutBindings.size())); - - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.composition)); - - // Pipeline layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.composition, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.composition)); - - // Descriptor sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.composition, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.composition)); - - // Image descriptors for the offscreen color attachments - VkDescriptorImageInfo texDescriptorPosition = vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.position.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - VkDescriptorImageInfo texDescriptorNormal = vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.normal.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - VkDescriptorImageInfo texDescriptorAlbedo = vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.albedo.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - std::vector writeDescriptorSets = { - // Binding 0: Position texture target - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 0, &texDescriptorPosition), - // Binding 1: Normals texture target - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, &texDescriptorNormal), - // Binding 2: Albedo texture target - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2, &texDescriptorAlbedo), - // Binding 4: Fragment shader lights - vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &buffers.lights.descriptor), - }; - - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - shaderStages[0] = loadShader(getShadersPath() + "subpasses/composition.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "subpasses/composition.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.composition, renderPass, 0); - - VkPipelineVertexInputStateCreateInfo emptyInputState{}; - emptyInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - - pipelineCI.pVertexInputState = &emptyInputState; - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - // Index of the subpass that this pipeline will be used in - pipelineCI.subpass = 1; - - depthStencilState.depthWriteEnable = VK_FALSE; - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.composition)); - - // Transparent (forward) pipeline - - // Descriptor set layout - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - }; - - descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.transparent)); - - // Pipeline layout - pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.transparent, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.transparent)); - - // Descriptor sets - allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.transparent, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.transparent)); - - writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.transparent, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &buffers.GBuffer.descriptor), - vks::initializers::writeDescriptorSet(descriptorSets.transparent, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, &texDescriptorPosition), - vks::initializers::writeDescriptorSet(descriptorSets.transparent, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.glass.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - - // Enable blending - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV}); - pipelineCI.layout = pipelineLayouts.transparent; - pipelineCI.subpass = 2; - - shaderStages[0] = loadShader(getShadersPath() + "subpasses/transparent.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "subpasses/transparent.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.transparent)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Matrices - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &buffers.GBuffer, sizeof(uboGBuffer)); - VK_CHECK_RESULT(buffers.GBuffer.map()); - - // Lights - vulkanDevice->createBuffer(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &buffers.lights, lights.size() * sizeof(Light)); - VK_CHECK_RESULT(buffers.lights.map()); - - // Update - updateUniformBufferDeferredMatrices(); - } - - void updateUniformBufferDeferredMatrices() - { - uboGBuffer.projection = camera.matrices.perspective; - uboGBuffer.view = camera.matrices.view; - uboGBuffer.model = glm::mat4(1.0f); - memcpy(buffers.GBuffer.mapped, &uboGBuffer, sizeof(uboGBuffer)); - } - - void initLights() - { - std::vector colors = - { - glm::vec3(1.0f, 1.0f, 1.0f), - glm::vec3(1.0f, 0.0f, 0.0f), - glm::vec3(0.0f, 1.0f, 0.0f), - glm::vec3(0.0f, 0.0f, 1.0f), - glm::vec3(1.0f, 1.0f, 0.0f), - }; - - std::random_device rndDevice; - std::default_random_engine rndGen(benchmark.active ? 0 : rndDevice()); - std::uniform_real_distribution rndDist(-1.0f, 1.0f); - std::uniform_real_distribution rndCol(0.0f, 0.5f); - - for (auto& light : lights) - { - light.position = glm::vec4(rndDist(rndGen) * 8.0f, 0.25f + std::abs(rndDist(rndGen)) * 4.0f, rndDist(rndGen) * 8.0f, 1.0f); - //light.color = colors[rndCol(rndGen)]; - light.color = glm::vec3(rndCol(rndGen), rndCol(rndGen), rndCol(rndGen)) * 2.0f; - light.radius = 1.0f + std::abs(rndDist(rndGen)); - } - - memcpy(buffers.lights.mapped, lights.data(), lights.size() * sizeof(Light)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - - // Command buffer to be submitted to the queue - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - - // Submit to queue - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - initLights(); - setupDescriptors(); - preparePipelines(); - prepareCompositionPass(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - if (camera.updated) { - updateUniformBufferDeferredMatrices(); - } - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Subpasses")) { - overlay->text("0: Deferred G-Buffer creation"); - overlay->text("1: Deferred composition"); - overlay->text("2: Forward transparency"); - } - if (overlay->header("Settings")) { - if (overlay->button("Randomize lights")) { - initLights(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/terraintessellation/terraintessellation.cpp b/examples/terraintessellation/terraintessellation.cpp deleted file mode 100644 index adc5ba32..00000000 --- a/examples/terraintessellation/terraintessellation.cpp +++ /dev/null @@ -1,752 +0,0 @@ -/* -* Vulkan Example - Dynamic terrain tessellation -* -* This samples draw a terrain from a heightmap texture and uses tessellation to add in details based on camera distance -* The height level is generated in the vertex shader by reading from the heightmap image -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" -#include "frustum.hpp" -#include -#include - -class VulkanExample : public VulkanExampleBase -{ -public: - bool wireframe = false; - bool tessellation = true; - - // Holds the buffers for rendering the tessellated terrain - struct { - struct Vertices { - VkBuffer buffer{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - } vertices; - struct Indices { - int count; - VkBuffer buffer{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - } indices; - } terrain; - - struct { - vks::Texture2D heightMap; - vks::Texture2D skySphere; - vks::Texture2DArray terrainArray; - } textures; - - struct { - vkglTF::Model skysphere; - } models; - - struct { - vks::Buffer terrainTessellation; - vks::Buffer skysphereVertex; - } uniformBuffers; - - // Shared values for tessellation control and evaluation stages - struct UniformDataTessellation { - glm::mat4 projection; - glm::mat4 modelview; - glm::vec4 lightPos = glm::vec4(-48.0f, -40.0f, 46.0f, 0.0f); - glm::vec4 frustumPlanes[6]; - float displacementFactor = 32.0f; - float tessellationFactor = 0.75f; - glm::vec2 viewportDim; - // Desired size of tessellated quad patch edge - float tessellatedEdgeSize = 20.0f; - } uniformDataTessellation; - - // Skysphere vertex shader stage - struct UniformDataVertex { - glm::mat4 mvp; - } uniformDataVertex; - - struct Pipelines { - VkPipeline terrain{ VK_NULL_HANDLE }; - VkPipeline wireframe{ VK_NULL_HANDLE }; - VkPipeline skysphere{ VK_NULL_HANDLE }; - } pipelines; - - struct { - VkDescriptorSetLayout terrain{ VK_NULL_HANDLE }; - VkDescriptorSetLayout skysphere{ VK_NULL_HANDLE }; - } descriptorSetLayouts; - - struct { - VkPipelineLayout terrain{ VK_NULL_HANDLE }; - VkPipelineLayout skysphere{ VK_NULL_HANDLE }; - } pipelineLayouts; - - struct { - VkDescriptorSet terrain{ VK_NULL_HANDLE }; - VkDescriptorSet skysphere{ VK_NULL_HANDLE }; - } descriptorSets; - - // If supported, this sample will gather pipeline statistics to show e.g. tessellation related information - struct { - VkBuffer buffer{ VK_NULL_HANDLE }; - VkDeviceMemory memory{ VK_NULL_HANDLE }; - } queryResult; - VkQueryPool queryPool{ VK_NULL_HANDLE }; - uint64_t pipelineStats[2] = { 0 }; - - // View frustum passed to tessellation control shader for culling - vks::Frustum frustum; - - VulkanExample() : VulkanExampleBase() - { - title = "Dynamic terrain tessellation"; - camera.type = Camera::CameraType::firstperson; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(-12.0f, 159.0f, 0.0f)); - camera.setTranslation(glm::vec3(18.0f, 22.5f, 57.5f)); - camera.movementSpeed = 10.0f; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.terrain, nullptr); - if (pipelines.wireframe != VK_NULL_HANDLE) { - vkDestroyPipeline(device, pipelines.wireframe, nullptr); - } - vkDestroyPipeline(device, pipelines.skysphere, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayouts.skysphere, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.terrain, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.terrain, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.skysphere, nullptr); - - uniformBuffers.skysphereVertex.destroy(); - uniformBuffers.terrainTessellation.destroy(); - - textures.heightMap.destroy(); - textures.skySphere.destroy(); - textures.terrainArray.destroy(); - - vkDestroyBuffer(device, terrain.vertices.buffer, nullptr); - vkFreeMemory(device, terrain.vertices.memory, nullptr); - vkDestroyBuffer(device, terrain.indices.buffer, nullptr); - vkFreeMemory(device, terrain.indices.memory, nullptr); - - if (queryPool != VK_NULL_HANDLE) { - vkDestroyQueryPool(device, queryPool, nullptr); - vkDestroyBuffer(device, queryResult.buffer, nullptr); - vkFreeMemory(device, queryResult.memory, nullptr); - } - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Tessellation shader support is required for this example - if (deviceFeatures.tessellationShader) { - enabledFeatures.tessellationShader = VK_TRUE; - } else { - vks::tools::exitFatal("Selected GPU does not support tessellation shaders!", VK_ERROR_FEATURE_NOT_PRESENT); - } - // Fill mode non solid is required for wireframe display - if (deviceFeatures.fillModeNonSolid) { - enabledFeatures.fillModeNonSolid = VK_TRUE; - }; - // Enable pipeline statistics if supported (to display them in the UI) - if (deviceFeatures.pipelineStatisticsQuery) { - enabledFeatures.pipelineStatisticsQuery = VK_TRUE; - }; - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - } - - // Setup a pool and a buffer for storing pipeline statistics results - void setupQueryResultBuffer() - { - uint32_t bufSize = 2 * sizeof(uint64_t); - - VkMemoryRequirements memReqs; - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkBufferCreateInfo bufferCreateInfo = - vks::initializers::bufferCreateInfo( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - bufSize); - - // Results are saved in a host visible buffer for easy access by the application - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &queryResult.buffer)); - vkGetBufferMemoryRequirements(device, queryResult.buffer, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &queryResult.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, queryResult.buffer, queryResult.memory, 0)); - - // Create query pool - if (deviceFeatures.pipelineStatisticsQuery) { - VkQueryPoolCreateInfo queryPoolInfo = {}; - queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - queryPoolInfo.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS; - queryPoolInfo.pipelineStatistics = - VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | - VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT; - queryPoolInfo.queryCount = 2; - VK_CHECK_RESULT(vkCreateQueryPool(device, &queryPoolInfo, NULL, &queryPool)); - } - } - - // Retrieves the results of the pipeline statistics query submitted to the command buffer - void getQueryResults() - { - // We use vkGetQueryResults to copy the results into a host visible buffer - vkGetQueryPoolResults( - device, - queryPool, - 0, - 1, - sizeof(pipelineStats), - pipelineStats, - sizeof(uint64_t), - VK_QUERY_RESULT_64_BIT); - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - models.skysphere.loadFromFile(getAssetPath() + "models/sphere.gltf", vulkanDevice, queue, glTFLoadingFlags); - - textures.skySphere.loadFromFile(getAssetPath() + "textures/skysphere_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - // Terrain textures are stored in a texture array with layers corresponding to terrain height - textures.terrainArray.loadFromFile(getAssetPath() + "textures/terrain_texturearray_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - - // Height data is stored in a one-channel texture - textures.heightMap.loadFromFile(getAssetPath() + "textures/terrain_heightmap_r16.ktx", VK_FORMAT_R16_UNORM, vulkanDevice, queue); - - VkSamplerCreateInfo samplerInfo = vks::initializers::samplerCreateInfo(); - - // Setup a mirroring sampler for the height map - vkDestroySampler(device, textures.heightMap.sampler, nullptr); - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; - samplerInfo.addressModeV = samplerInfo.addressModeU; - samplerInfo.addressModeW = samplerInfo.addressModeU; - samplerInfo.compareOp = VK_COMPARE_OP_NEVER; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = (float)textures.heightMap.mipLevels; - samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &textures.heightMap.sampler)); - textures.heightMap.descriptor.sampler = textures.heightMap.sampler; - - // Setup a repeating sampler for the terrain texture layers - vkDestroySampler(device, textures.terrainArray.sampler, nullptr); - samplerInfo = vks::initializers::samplerCreateInfo(); - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeV = samplerInfo.addressModeU; - samplerInfo.addressModeW = samplerInfo.addressModeU; - samplerInfo.compareOp = VK_COMPARE_OP_NEVER; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = (float)textures.terrainArray.mipLevels; - samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - if (deviceFeatures.samplerAnisotropy) { - samplerInfo.maxAnisotropy = 4.0f; - samplerInfo.anisotropyEnable = VK_TRUE; - } - VK_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &textures.terrainArray.sampler)); - textures.terrainArray.descriptor.sampler = textures.terrainArray.sampler; - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - if (deviceFeatures.pipelineStatisticsQuery) { - vkCmdResetQueryPool(drawCmdBuffers[i], queryPool, 0, 2); - } - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdSetLineWidth(drawCmdBuffers[i], 1.0f); - - VkDeviceSize offsets[1] = { 0 }; - - // Skysphere - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skysphere); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.skysphere, 0, 1, &descriptorSets.skysphere, 0, nullptr); - models.skysphere.draw(drawCmdBuffers[i]); - - // Tessellated terrain - if (deviceFeatures.pipelineStatisticsQuery) { - // Begin pipeline statistics query - vkCmdBeginQuery(drawCmdBuffers[i], queryPool, 0, 0); - } - // Render - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.terrain); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.terrain, 0, 1, &descriptorSets.terrain, 0, nullptr); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &terrain.vertices.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], terrain.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(drawCmdBuffers[i], terrain.indices.count, 1, 0, 0, 0); - if (deviceFeatures.pipelineStatisticsQuery) { - // End pipeline statistics query - vkCmdEndQuery(drawCmdBuffers[i], queryPool, 0); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - // Generate a terrain quad patch with normals based on heightmap data - void generateTerrain() - { - const uint32_t patchSize{ 64 }; - const float uvScale{ 1.0f }; - - uint16_t* heightdata; - uint32_t dim; - uint32_t scale; - - ktxResult result; - ktxTexture* ktxTexture; - - // We load the heightmap from an un-compressed ktx image with one channel that contains heights - std::string filename = getAssetPath() + "textures/terrain_heightmap_r16.ktx"; -#if defined(__ANDROID__) - // On Android we need to load the file using the asset manager - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); - assert(asset); - size_t size = AAsset_getLength(asset); - assert(size > 0); - ktx_uint8_t* textureData = new ktx_uint8_t[size]; - AAsset_read(asset, textureData, size); - AAsset_close(asset); - result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); - delete[] textureData; - -#else - result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); -#endif - assert(result == KTX_SUCCESS); - ktx_size_t ktxSize = ktxTexture_GetImageSize(ktxTexture, 0); - ktx_uint8_t* ktxImage = ktxTexture_GetData(ktxTexture); - dim = ktxTexture->baseWidth; - heightdata = new uint16_t[dim * dim]; - memcpy(heightdata, ktxImage, ktxSize); - scale = dim / patchSize; - ktxTexture_Destroy(ktxTexture); - - const uint32_t vertexCount = patchSize * patchSize; - // We use the Vertex definition from the glTF model loader, so we can re-use the vertex input state - vkglTF::Vertex *vertices = new vkglTF::Vertex[vertexCount]; - - const float wx = 2.0f; - const float wy = 2.0f; - - // Generate a two-dimensional vertex patch - for (auto x = 0; x < patchSize; x++) { - for (auto y = 0; y < patchSize; y++) { - uint32_t index = (x + y * patchSize); - vertices[index].pos[0] = x * wx + wx / 2.0f - (float)patchSize * wx / 2.0f; - vertices[index].pos[1] = 0.0f; - vertices[index].pos[2] = y * wy + wy / 2.0f - (float)patchSize * wy / 2.0f; - vertices[index].uv = glm::vec2((float)x / (patchSize - 1), (float)y / (patchSize - 1)) * uvScale; - } - } - - // Calculate normals from the height map using a sobel filter - for (auto x = 0; x < patchSize; x++) { - for (auto y = 0; y < patchSize; y++) { - // We get - float heights[3][3]; - for (auto sx = -1; sx <= 1; sx++) { - for (auto sy = -1; sy <= 1; sy++) { - // Get height at sampled position from heightmap - glm::ivec2 rpos = glm::ivec2(x + sx, y + sy) * glm::ivec2(scale); - rpos.x = std::max(0, std::min(rpos.x, (int)dim - 1)); - rpos.y = std::max(0, std::min(rpos.y, (int)dim - 1)); - rpos /= glm::ivec2(scale); - heights[sx + 1][sy + 1] = *(heightdata + (rpos.x + rpos.y * dim) * scale) / 65535.0f; - } - } - glm::vec3 normal; - // Gx sobel filter - normal.x = heights[0][0] - heights[2][0] + 2.0f * heights[0][1] - 2.0f * heights[2][1] + heights[0][2] - heights[2][2]; - // Gy sobel filter - normal.z = heights[0][0] + 2.0f * heights[1][0] + heights[2][0] - heights[0][2] - 2.0f * heights[1][2] - heights[2][2]; - // Calculate missing up component of the normal using the filtered x and y axis - // The first value controls the bump strength - normal.y = 0.25f * sqrt( 1.0f - normal.x * normal.x - normal.z * normal.z); - - vertices[x + y * patchSize].normal = glm::normalize(normal * glm::vec3(2.0f, 1.0f, 2.0f)); - } - } - - delete[] heightdata; - - // Generate indices - const uint32_t w = (patchSize - 1); - const uint32_t indexCount = w * w * 4; - uint32_t *indices = new uint32_t[indexCount]; - for (auto x = 0; x < w; x++) - { - for (auto y = 0; y < w; y++) - { - uint32_t index = (x + y * w) * 4; - indices[index] = (x + y * patchSize); - indices[index + 1] = indices[index] + patchSize; - indices[index + 2] = indices[index + 1] + 1; - indices[index + 3] = indices[index] + 1; - } - } - terrain.indices.count = indexCount; - - // Upload vertices and indices to device - - uint32_t vertexBufferSize = vertexCount * sizeof(vkglTF::Vertex); - uint32_t indexBufferSize = indexCount * sizeof(uint32_t); - - struct { - VkBuffer buffer; - VkDeviceMemory memory; - } vertexStaging, indexStaging; - - // Stage the terrain vertex data to the device - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - vertexBufferSize, - &vertexStaging.buffer, - &vertexStaging.memory, - vertices)); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - indexBufferSize, - &indexStaging.buffer, - &indexStaging.memory, - indices)); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - vertexBufferSize, - &terrain.vertices.buffer, - &terrain.vertices.memory)); - - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - indexBufferSize, - &terrain.indices.buffer, - &terrain.indices.memory)); - - // Copy from staging buffers - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - VkBufferCopy copyRegion = {}; - - copyRegion.size = vertexBufferSize; - vkCmdCopyBuffer( - copyCmd, - vertexStaging.buffer, - terrain.vertices.buffer, - 1, - ©Region); - - copyRegion.size = indexBufferSize; - vkCmdCopyBuffer( - copyCmd, - indexStaging.buffer, - terrain.indices.buffer, - 1, - ©Region); - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - vkDestroyBuffer(device, vertexStaging.buffer, nullptr); - vkFreeMemory(device, vertexStaging.memory, nullptr); - vkDestroyBuffer(device, indexStaging.buffer, nullptr); - vkFreeMemory(device, indexStaging.memory, nullptr); - - delete[] vertices; - delete[] indices; - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layouts - VkDescriptorSetLayoutCreateInfo descriptorLayout; - std::vector setLayoutBindings; - - // Terrain - setLayoutBindings = { - // Binding 0 : Shared Tessellation shader ubo - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0), - // Binding 1 : Height map - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 2 : Terrain texture array layers - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - }; - descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.terrain)); - - // Skysphere - setLayoutBindings = { - // Binding 0 : Vertex shader ubo - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Color map - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.skysphere)); - // Sets - VkDescriptorSetAllocateInfo allocInfo; - std::vector writeDescriptorSets; - - // Terrain - allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.terrain, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.terrain)); - - writeDescriptorSets = { - // Binding 0 : Shared tessellation shader ubo - vks::initializers::writeDescriptorSet(descriptorSets.terrain, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.terrainTessellation.descriptor), - // Binding 1 : Height map - vks::initializers::writeDescriptorSet(descriptorSets.terrain, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.heightMap.descriptor), - // Binding 2 : Terrain texture array layers - vks::initializers::writeDescriptorSet(descriptorSets.terrain, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &textures.terrainArray.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Skysphere - allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.skysphere, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.skysphere)); - writeDescriptorSets = { - // Binding 0 : Vertex shader ubo - vks::initializers::writeDescriptorSet(descriptorSets.skysphere, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.skysphereVertex.descriptor), - // Binding 1 : Fragment shader color map - vks::initializers::writeDescriptorSet(descriptorSets.skysphere, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.skySphere.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layouts - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo; - - pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.terrain, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.terrain)); - - pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.skysphere, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.skysphere)); - - // Pipelines - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // We render the terrain as a grid of quad patches - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, 0, VK_FALSE); - VkPipelineTessellationStateCreateInfo tessellationState = vks::initializers::pipelineTessellationStateCreateInfo(4); - // Terrain tessellation pipeline - shaderStages[0] = loadShader(getShadersPath() + "terraintessellation/terrain.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "terraintessellation/terrain.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - shaderStages[2] = loadShader(getShadersPath() + "terraintessellation/terrain.tesc.spv", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); - shaderStages[3] = loadShader(getShadersPath() + "terraintessellation/terrain.tese.spv", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.terrain, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.pTessellationState = &tessellationState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.terrain)); - - // Terrain wireframe pipeline (if devie supports it) - if (deviceFeatures.fillModeNonSolid) { - rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); - }; - - // Skysphere pipeline - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - rasterizationState.polygonMode = VK_POLYGON_MODE_FILL; - // Revert to triangle list topology - inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - // Reset tessellation state - pipelineCI.pTessellationState = nullptr; - // Don't write to depth buffer - depthStencilState.depthWriteEnable = VK_FALSE; - pipelineCI.stageCount = 2; - pipelineCI.layout = pipelineLayouts.skysphere; - shaderStages[0] = loadShader(getShadersPath() + "terraintessellation/skysphere.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "terraintessellation/skysphere.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.skysphere)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Shared tessellation shader stages uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.terrainTessellation, sizeof(UniformDataTessellation))); - - // Skysphere vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.skysphereVertex, sizeof(UniformDataVertex))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffers.terrainTessellation.map()); - VK_CHECK_RESULT(uniformBuffers.skysphereVertex.map()); - } - - void updateUniformBuffers() - { - // Tessellation - uniformDataTessellation.projection = camera.matrices.perspective; - uniformDataTessellation.modelview = camera.matrices.view * glm::mat4(1.0f); - uniformDataTessellation.lightPos.y = -0.5f - uniformDataTessellation.displacementFactor; // todo: Not uesed yet - uniformDataTessellation.viewportDim = glm::vec2((float)width, (float)height); - - frustum.update(uniformDataTessellation.projection * uniformDataTessellation.modelview); - memcpy(uniformDataTessellation.frustumPlanes, frustum.planes.data(), sizeof(glm::vec4) * 6); - - float savedFactor = uniformDataTessellation.tessellationFactor; - if (!tessellation) - { - // Setting this to zero sets all tessellation factors to 1.0 in the shader - uniformDataTessellation.tessellationFactor = 0.0f; - } - - memcpy(uniformBuffers.terrainTessellation.mapped, &uniformDataTessellation, sizeof(UniformDataTessellation)); - - if (!tessellation) - { - uniformDataTessellation.tessellationFactor = savedFactor; - } - - // Vertex shader - uniformDataVertex.mvp = camera.matrices.perspective * glm::mat4(glm::mat3(camera.matrices.view)); - memcpy(uniformBuffers.skysphereVertex.mapped, &uniformDataVertex, sizeof(UniformDataVertex)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - generateTerrain(); - if (deviceFeatures.pipelineStatisticsQuery) { - setupQueryResultBuffer(); - } - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - // Read query results for displaying in next frame (if the device supports pipeline statistics) - if (deviceFeatures.pipelineStatisticsQuery) { - getQueryResults(); - } - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - - if (overlay->checkBox("Tessellation", &tessellation)) { - updateUniformBuffers(); - } - if (overlay->inputFloat("Factor", &uniformDataTessellation.tessellationFactor, 0.05f, 2)) { - updateUniformBuffers(); - } - if (deviceFeatures.fillModeNonSolid) { - if (overlay->checkBox("Wireframe", &wireframe)) { - buildCommandBuffers(); - } - } - } - if (deviceFeatures.pipelineStatisticsQuery) { - if (overlay->header("Pipeline statistics")) { - overlay->text("VS invocations: %d", pipelineStats[0]); - overlay->text("TE invocations: %d", pipelineStats[1]); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/tessellation/tessellation.cpp b/examples/tessellation/tessellation.cpp deleted file mode 100644 index b3aa2040..00000000 --- a/examples/tessellation/tessellation.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* -* Vulkan Example - Tessellation shader PN triangles -* -* Based on http://alex.vlachos.com/graphics/CurvedPNTriangles.pdf -* Shaders based on http://onrendering.blogspot.de/2011/12/tessellation-on-gpu-curved-pn-triangles.html -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - bool splitScreen = true; - bool wireframe = true; - - vkglTF::Model model; - - // One uniform data block is used by both tessellation shader stages - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - float tessAlpha = 1.0f; - float tessLevel = 3.0f; - } uniformData; - vks::Buffer uniformBuffer; - - struct Pipelines { - VkPipeline solid{ VK_NULL_HANDLE }; - VkPipeline wire{ VK_NULL_HANDLE }; - VkPipeline solidPassThrough{ VK_NULL_HANDLE }; - VkPipeline wirePassThrough{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Tessellation shader (PN Triangles)"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -4.0f)); - camera.setRotation(glm::vec3(-350.0f, 60.0f, 0.0f)); - camera.setPerspective(45.0f, (float)(width * ((splitScreen) ? 0.5f : 1.0f)) / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - // Clean up used Vulkan resources - // Note : Inherited destructor cleans up resources stored in base class - vkDestroyPipeline(device, pipelines.solid, nullptr); - if (pipelines.wire != VK_NULL_HANDLE) { - vkDestroyPipeline(device, pipelines.wire, nullptr); - }; - vkDestroyPipeline(device, pipelines.solidPassThrough, nullptr); - if (pipelines.wirePassThrough != VK_NULL_HANDLE) { - vkDestroyPipeline(device, pipelines.wirePassThrough, nullptr); - }; - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - uniformBuffer.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Example requires tessellation shaders - if (deviceFeatures.tessellationShader) { - enabledFeatures.tessellationShader = VK_TRUE; - } - else { - vks::tools::exitFatal("Selected GPU does not support tessellation shaders!", VK_ERROR_FEATURE_NOT_PRESENT); - } - // Fill mode non solid is required for wireframe display - if (deviceFeatures.fillModeNonSolid) { - enabledFeatures.fillModeNonSolid = VK_TRUE; - } - else { - wireframe = false; - } - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { {0.5f, 0.5f, 0.5f, 0.0f} }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport(splitScreen ? (float)width / 2.0f : (float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdSetLineWidth(drawCmdBuffers[i], 1.0f); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - if (splitScreen) { - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wirePassThrough : pipelines.solidPassThrough); - model.draw(drawCmdBuffers[i], vkglTF::RenderFlags::BindImages, pipelineLayout); - viewport.x = float(width) / 2; - } - - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wire : pipelines.solid); - model.draw(drawCmdBuffers[i], vkglTF::RenderFlags::BindImages, pipelineLayout); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - model.loadFromFile(getAssetPath() + "models/deer.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY); - } - - void setupDescriptors() - { - // Pool - const std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - const std::vector setLayoutBindings = { - // Binding 0 : Tessellation shader ubo - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0 : Tessellation shader ubo - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout uses set 0 for passing tessellation shader ubos and set 1 for fragment shader images (taken from glTF model) - const std::vector setLayouts = { - descriptorSetLayout, - vkglTF::descriptorSetLayoutImage, - }; - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), 2); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables, 0); - VkPipelineTessellationStateCreateInfo tessellationState = vks::initializers::pipelineTessellationStateCreateInfo(3); - std::array shaderStages; - - // Tessellation pipelines - shaderStages[0] = loadShader(getShadersPath() + "tessellation/base.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "tessellation/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - shaderStages[2] = loadShader(getShadersPath() + "tessellation/pntriangles.tesc.spv", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); - shaderStages[3] = loadShader(getShadersPath() + "tessellation/pntriangles.tese.spv", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.pTessellationState = &tessellationState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.renderPass = renderPass; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - // Tessellation pipelines - // Solid - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.solid)); - // Wireframe - if (deviceFeatures.fillModeNonSolid) { - rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wire)); - } - - // Pass through pipelines - // Load pass through tessellation shaders (Vert and frag are reused) - shaderStages[2] = loadShader(getShadersPath() + "tessellation/passthrough.tesc.spv", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); - shaderStages[3] = loadShader(getShadersPath() + "tessellation/passthrough.tese.spv", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); - - // Solid - rasterizationState.polygonMode = VK_POLYGON_MODE_FILL; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.solidPassThrough)); - // Wireframe - if (deviceFeatures.fillModeNonSolid) { - rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wirePassThrough)); - } - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Tessellation evaluation shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - // Adjust camera perspective if split screen is enabled - camera.setPerspective(45.0f, (float)(width * ((splitScreen) ? 0.5f : 1.0f)) / (float)height, 0.1f, 256.0f); - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - // Tessellation evaluation uniform block - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->inputFloat("Tessellation level", &uniformData.tessLevel, 0.25f, 2)) { - updateUniformBuffers(); - } - if (deviceFeatures.fillModeNonSolid) { - if (overlay->checkBox("Wireframe", &wireframe)) { - updateUniformBuffers(); - buildCommandBuffers(); - } - if (overlay->checkBox("Splitscreen", &splitScreen)) { - camera.setPerspective(45.0f, (float)(width * ((splitScreen) ? 0.5f : 1.0f)) / (float)height, 0.1f, 256.0f); - updateUniformBuffers(); - buildCommandBuffers(); - } - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/textoverlay/textoverlay.cpp b/examples/textoverlay/textoverlay.cpp deleted file mode 100644 index 648f3058..00000000 --- a/examples/textoverlay/textoverlay.cpp +++ /dev/null @@ -1,719 +0,0 @@ -/* -* Vulkan Example - Text overlay rendering on-top of an existing scene using a separate render pass -* -* This sample renders a basic text overlay on top of a 3D scene that can be used e.g. for debug purposes -* For a more complete GUI sample see the ImGui sample -* -* Copyright (C) 2016-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include -#include -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" -#include "../external/stb/stb_font_consolas_24_latin1.inl" - -// Max. number of chars the text overlay buffer can hold -#define TEXTOVERLAY_MAX_CHAR_COUNT 2048 - -/* - Mostly self-contained text overlay class - This class contains all Vulkan resources for drawing the text overlay - It can be plugged into an existing renderpass/command buffer -*/ -class TextOverlay -{ -private: - // Created by this class - // Font image - VkSampler sampler; - VkImage image; - VkImageView view; - VkDeviceMemory imageMemory; - // Character vertex buffer - VkBuffer buffer; - VkDeviceMemory memory; - VkDescriptorPool descriptorPool; - VkDescriptorSetLayout descriptorSetLayout; - VkDescriptorSet descriptorSet; - VkPipelineLayout pipelineLayout; - VkPipelineCache pipelineCache; - VkPipeline pipeline; - - // Passed from the sample - VkRenderPass renderPass; - VkQueue queue; - vks::VulkanDevice* vulkanDevice; - uint32_t* frameBufferWidth; - uint32_t* frameBufferHeight; - std::vector shaderStages; - float scale; - - // Pointer to mapped vertex buffer - glm::vec4 *mapped = nullptr; - - stb_fontchar stbFontData[STB_FONT_consolas_24_latin1_NUM_CHARS]; -public: - enum TextAlign { alignLeft, alignCenter, alignRight }; - - uint32_t numLetters; - bool visible = true; - - TextOverlay( - vks::VulkanDevice *vulkanDevice, - VkQueue queue, - VkRenderPass renderPass, - uint32_t *framebufferwidth, - uint32_t *framebufferheight, - float scale, - std::vector shaderstages) - { - this->vulkanDevice = vulkanDevice; - this->queue = queue; - this->shaderStages = shaderstages; - this->frameBufferWidth = framebufferwidth; - this->frameBufferHeight = framebufferheight; - this->scale = scale; - this->renderPass = renderPass; - - prepareResources(); - preparePipeline(); - } - - ~TextOverlay() - { - // Free up all Vulkan resources requested by the text overlay - vkDestroySampler(vulkanDevice->logicalDevice, sampler, nullptr); - vkDestroyImage(vulkanDevice->logicalDevice, image, nullptr); - vkDestroyImageView(vulkanDevice->logicalDevice, view, nullptr); - vkDestroyBuffer(vulkanDevice->logicalDevice, buffer, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, memory, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, imageMemory, nullptr); - vkDestroyDescriptorSetLayout(vulkanDevice->logicalDevice, descriptorSetLayout, nullptr); - vkDestroyDescriptorPool(vulkanDevice->logicalDevice, descriptorPool, nullptr); - vkDestroyPipelineLayout(vulkanDevice->logicalDevice, pipelineLayout, nullptr); - vkDestroyPipelineCache(vulkanDevice->logicalDevice, pipelineCache, nullptr); - vkDestroyPipeline(vulkanDevice->logicalDevice, pipeline, nullptr); - } - - // Prepare all vulkan resources required to render the font - // The text overlay uses separate resources for descriptors (pool, sets, layouts), pipelines and command buffers - void prepareResources() - { - const uint32_t fontWidth = STB_FONT_consolas_24_latin1_BITMAP_WIDTH; - const uint32_t fontHeight = STB_FONT_consolas_24_latin1_BITMAP_HEIGHT; - - static unsigned char font24pixels[fontHeight][fontWidth]; - stb_font_consolas_24_latin1(stbFontData, font24pixels, fontHeight); - - // Vertex buffer - VkDeviceSize bufferSize = TEXTOVERLAY_MAX_CHAR_COUNT * sizeof(glm::vec4); - - VkBufferCreateInfo bufferInfo = vks::initializers::bufferCreateInfo(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, bufferSize); - VK_CHECK_RESULT(vkCreateBuffer(vulkanDevice->logicalDevice, &bufferInfo, nullptr, &buffer)); - - VkMemoryRequirements memReqs; - VkMemoryAllocateInfo allocInfo = vks::initializers::memoryAllocateInfo(); - - vkGetBufferMemoryRequirements(vulkanDevice->logicalDevice, buffer, &memReqs); - allocInfo.allocationSize = memReqs.size; - allocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - - VK_CHECK_RESULT(vkAllocateMemory(vulkanDevice->logicalDevice, &allocInfo, nullptr, &memory)); - VK_CHECK_RESULT(vkBindBufferMemory(vulkanDevice->logicalDevice, buffer, memory, 0)); - - // Font texture - VkImageCreateInfo imageInfo = vks::initializers::imageCreateInfo(); - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.format = VK_FORMAT_R8_UNORM; - imageInfo.extent.width = fontWidth; - imageInfo.extent.height = fontHeight; - imageInfo.extent.depth = 1; - imageInfo.mipLevels = 1; - imageInfo.arrayLayers = 1; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VK_CHECK_RESULT(vkCreateImage(vulkanDevice->logicalDevice, &imageInfo, nullptr, &image)); - - vkGetImageMemoryRequirements(vulkanDevice->logicalDevice, image, &memReqs); - allocInfo.allocationSize = memReqs.size; - allocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - VK_CHECK_RESULT(vkAllocateMemory(vulkanDevice->logicalDevice, &allocInfo, nullptr, &imageMemory)); - VK_CHECK_RESULT(vkBindImageMemory(vulkanDevice->logicalDevice, image, imageMemory, 0)); - - // Staging - - struct { - VkDeviceMemory memory; - VkBuffer buffer; - } stagingBuffer; - - VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = allocInfo.allocationSize; - bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VK_CHECK_RESULT(vkCreateBuffer(vulkanDevice->logicalDevice, &bufferCreateInfo, nullptr, &stagingBuffer.buffer)); - - // Get memory requirements for the staging buffer (alignment, memory type bits) - vkGetBufferMemoryRequirements(vulkanDevice->logicalDevice, stagingBuffer.buffer, &memReqs); - - allocInfo.allocationSize = memReqs.size; - // Get memory type index for a host visible buffer - allocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - - VK_CHECK_RESULT(vkAllocateMemory(vulkanDevice->logicalDevice, &allocInfo, nullptr, &stagingBuffer.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(vulkanDevice->logicalDevice, stagingBuffer.buffer, stagingBuffer.memory, 0)); - - uint8_t *data; - VK_CHECK_RESULT(vkMapMemory(vulkanDevice->logicalDevice, stagingBuffer.memory, 0, allocInfo.allocationSize, 0, (void **)&data)); - // Size of the font texture is WIDTH * HEIGHT * 1 byte (only one channel) - memcpy(data, &font24pixels[0][0], fontWidth * fontHeight); - vkUnmapMemory(vulkanDevice->logicalDevice, stagingBuffer.memory); - - // Copy to image - - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // Prepare for transfer - vks::tools::setImageLayout( - copyCmd, - image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - VkBufferImageCopy bufferCopyRegion = {}; - bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - bufferCopyRegion.imageSubresource.mipLevel = 0; - bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = fontWidth; - bufferCopyRegion.imageExtent.height = fontHeight; - bufferCopyRegion.imageExtent.depth = 1; - - vkCmdCopyBufferToImage( - copyCmd, - stagingBuffer.buffer, - image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &bufferCopyRegion - ); - - // Prepare for shader read - vks::tools::setImageLayout( - copyCmd, - image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - vulkanDevice->flushCommandBuffer(copyCmd, queue); - - vkFreeMemory(vulkanDevice->logicalDevice, stagingBuffer.memory, nullptr); - vkDestroyBuffer(vulkanDevice->logicalDevice, stagingBuffer.buffer, nullptr); - - VkImageViewCreateInfo imageViewInfo = vks::initializers::imageViewCreateInfo(); - imageViewInfo.image = image; - imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageViewInfo.format = imageInfo.format; - imageViewInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; - imageViewInfo.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - VK_CHECK_RESULT(vkCreateImageView(vulkanDevice->logicalDevice, &imageViewInfo, nullptr, &view)); - - // Sampler - VkSamplerCreateInfo samplerInfo = vks::initializers::samplerCreateInfo(); - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.compareOp = VK_COMPARE_OP_NEVER; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 1.0f; - samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(vulkanDevice->logicalDevice, &samplerInfo, nullptr, &sampler)); - - // Descriptor - // Font uses a separate descriptor pool - std::array poolSizes; - poolSizes[0] = vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1); - - VkDescriptorPoolCreateInfo descriptorPoolInfo = - vks::initializers::descriptorPoolCreateInfo( - static_cast(poolSizes.size()), - poolSizes.data(), - 1); - - VK_CHECK_RESULT(vkCreateDescriptorPool(vulkanDevice->logicalDevice, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor set layout - std::array setLayoutBindings; - setLayoutBindings[0] = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(vulkanDevice->logicalDevice, &descriptorSetLayoutInfo, nullptr, &descriptorSetLayout)); - - // Descriptor set - VkDescriptorSetAllocateInfo descriptorSetAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(vulkanDevice->logicalDevice, &descriptorSetAllocInfo, &descriptorSet)); - - // Descriptor for the font image - VkDescriptorImageInfo texDescriptor = vks::initializers::descriptorImageInfo(sampler, view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - std::array writeDescriptorSets; - writeDescriptorSets[0] = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &texDescriptor); - vkUpdateDescriptorSets(vulkanDevice->logicalDevice, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - } - - // Prepare a separate pipeline for the font rendering decoupled from the main application - void preparePipeline() - { - // Pipeline cache - VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {}; - pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - VK_CHECK_RESULT(vkCreatePipelineCache(vulkanDevice->logicalDevice, &pipelineCacheCreateInfo, nullptr, &pipelineCache)); - - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(vulkanDevice->logicalDevice, &pipelineLayoutInfo, nullptr, &pipelineLayout)); - - // Enable blending, using alpha from red channel of the font texture (see text.frag) - VkPipelineColorBlendAttachmentState blendAttachmentState{}; - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE, 0); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - - std::array vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(glm::vec4), VK_VERTEX_INPUT_RATE_VERTEX), - vks::initializers::vertexInputBindingDescription(1, sizeof(glm::vec4), VK_VERTEX_INPUT_RATE_VERTEX), - }; - std::array vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32_SFLOAT, 0), // Location 0: Position - vks::initializers::vertexInputAttributeDescription(1, 1, VK_FORMAT_R32G32_SFLOAT, sizeof(glm::vec2)), // Location 1: UV - }; - - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &vertexInputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(vulkanDevice->logicalDevice, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); - } - - // Map buffer - void beginTextUpdate() - { - VK_CHECK_RESULT(vkMapMemory(vulkanDevice->logicalDevice, memory, 0, VK_WHOLE_SIZE, 0, (void **)&mapped)); - numLetters = 0; - } - - // Add text to the current buffer - void addText(std::string text, float x, float y, TextAlign align) - { - const uint32_t firstChar = STB_FONT_consolas_24_latin1_FIRST_CHAR; - - assert(mapped != nullptr); - - const float charW = 1.5f * scale / *frameBufferWidth; - const float charH = 1.5f * scale / *frameBufferHeight; - - float fbW = (float)*frameBufferWidth; - float fbH = (float)*frameBufferHeight; - x = (x / fbW * 2.0f) - 1.0f; - y = (y / fbH * 2.0f) - 1.0f; - - // Calculate text width - float textWidth = 0; - for (auto letter : text) - { - stb_fontchar *charData = &stbFontData[(uint32_t)letter - firstChar]; - textWidth += charData->advance * charW; - } - - switch (align) - { - case alignRight: - x -= textWidth; - break; - case alignCenter: - x -= textWidth / 2.0f; - break; - case alignLeft: - break; - } - - // Generate a uv mapped quad per char in the new text - for (auto letter : text) - { - stb_fontchar *charData = &stbFontData[(uint32_t)letter - firstChar]; - - mapped->x = (x + (float)charData->x0 * charW); - mapped->y = (y + (float)charData->y0 * charH); - mapped->z = charData->s0; - mapped->w = charData->t0; - mapped++; - - mapped->x = (x + (float)charData->x1 * charW); - mapped->y = (y + (float)charData->y0 * charH); - mapped->z = charData->s1; - mapped->w = charData->t0; - mapped++; - - mapped->x = (x + (float)charData->x0 * charW); - mapped->y = (y + (float)charData->y1 * charH); - mapped->z = charData->s0; - mapped->w = charData->t1; - mapped++; - - mapped->x = (x + (float)charData->x1 * charW); - mapped->y = (y + (float)charData->y1 * charH); - mapped->z = charData->s1; - mapped->w = charData->t1; - mapped++; - - x += charData->advance * charW; - - numLetters++; - } - } - - // Unmap buffer and update command buffers - void endTextUpdate() - { - vkUnmapMemory(vulkanDevice->logicalDevice, memory); - mapped = nullptr; - //updateCommandBuffers(); - } - - // Issue the draw commands for the characters of the overlay - void draw(VkCommandBuffer cmdBuffer) - { - vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - - VkDeviceSize offsets = 0; - vkCmdBindVertexBuffers(cmdBuffer, 0, 1, &buffer, &offsets); - vkCmdBindVertexBuffers(cmdBuffer, 1, 1, &buffer, &offsets); - // One draw command for every character. This is okay for a debug overlay, but not optimal - // In a real-world application one would try to batch draw commands - for (uint32_t j = 0; j < numLetters; j++) { - vkCmdDraw(cmdBuffer, 4, 1, j * 4, 0); - } - } -}; - -/* - Vulkan example main class -*/ -class VulkanExample : public VulkanExampleBase -{ -public: - TextOverlay* textOverlay{ nullptr }; - - vkglTF::Model model; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 lightPos = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); - } uniformData; - vks::Buffer uniformBuffer; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Text overlay"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -2.5f)); - camera.setRotation(glm::vec3(-25.0f, -0.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - settings.overlay = false; - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - delete(textOverlay); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[3]; - - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - model.draw(drawCmdBuffers[i]); - - if (textOverlay->visible) { - textOverlay->draw(drawCmdBuffers[i]); - } - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - - vkQueueWaitIdle(queue); - } - - // Update the text buffer displayed by the text overlay - void updateTextOverlay(void) - { - uint32_t lastNumLetters = textOverlay->numLetters; - - textOverlay->beginTextUpdate(); - - textOverlay->addText(title, 5.0f * ui.scale, 5.0f * ui.scale, TextOverlay::alignLeft); - - std::stringstream ss; - ss << std::fixed << std::setprecision(2) << (frameTimer * 1000.0f) << "ms (" << lastFPS << " fps)"; - textOverlay->addText(ss.str(), 5.0f * ui.scale, 25.0f * ui.scale, TextOverlay::alignLeft); - - textOverlay->addText(deviceProperties.deviceName, 5.0f * ui.scale, 45.0f * ui.scale, TextOverlay::alignLeft); - - // Display current model view matrix - textOverlay->addText("model view matrix", (float)width - 5.0f * ui.scale, 5.0f * ui.scale, TextOverlay::alignRight); - - for (uint32_t i = 0; i < 4; i++) - { - ss.str(""); - ss << std::fixed << std::setprecision(2) << std::showpos; - ss << uniformData.modelView[0][i] << " " << uniformData.modelView[1][i] << " " << uniformData.modelView[2][i] << " " << uniformData.modelView[3][i]; - textOverlay->addText(ss.str(), (float)width - 5.0f * ui.scale, (25.0f + (float)i * 20.0f) * ui.scale, TextOverlay::alignRight); - } - - glm::vec3 projected = glm::project(glm::vec3(0.0f), uniformData.modelView, uniformData.projection, glm::vec4(0, 0, (float)width, (float)height)); - textOverlay->addText("A torus knot", projected.x, projected.y, TextOverlay::alignCenter); - -#if defined(__ANDROID__) -#else - textOverlay->addText("Press \"space\" to toggle text overlay", 5.0f * ui.scale, 65.0f * ui.scale, TextOverlay::alignLeft); - textOverlay->addText("Hold middle mouse button and drag to move", 5.0f * ui.scale, 85.0f * ui.scale, TextOverlay::alignLeft); -#endif - textOverlay->endTextUpdate(); - - // If the no. of letters changed, the no. of draw commands also changes which requires a rebuild of the command buffers - if (lastNumLetters != textOverlay->numLetters) { - std::cout << "rebuild cb\n"; - buildCommandBuffers(); - } - } - - void loadAssets() - { - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - model.loadFromFile(getAssetPath() + "models/torusknot.gltf", vulkanDevice, queue, glTFLoadingFlags); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV}); - - shaderStages[0] = loadShader(getShadersPath() + "textoverlay/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "textoverlay/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepareTextOverlay() - { - // Load the text rendering shaders - std::vector shaderStages; - shaderStages.push_back(loadShader(getShadersPath() + "textoverlay/text.vert.spv", VK_SHADER_STAGE_VERTEX_BIT)); - shaderStages.push_back(loadShader(getShadersPath() + "textoverlay/text.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT)); - - textOverlay = new TextOverlay( - vulkanDevice, - queue, - renderPass, - &width, - &height, - ui.scale, - shaderStages - ); - updateTextOverlay(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - prepareTextOverlay(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - if (camera.updated) { - updateTextOverlay(); - } - draw(); - } - - virtual void keyPressed(uint32_t keyCode) - { - switch (keyCode) - { - case KEY_KPADD: - case KEY_SPACE: - textOverlay->visible = !textOverlay->visible; - buildCommandBuffers(); - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/texture/texture.cpp b/examples/texture/texture.cpp deleted file mode 100644 index d8dee7cb..00000000 --- a/examples/texture/texture.cpp +++ /dev/null @@ -1,683 +0,0 @@ -/* -* Vulkan Example - Texture loading (and display) example (including mip maps) -* -* This sample shows how to upload a 2D texture to the device and how to display it. In Vulkan this is done using images, views and samplers. -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include -#include - -// Vertex layout for this example -struct Vertex { - float pos[3]; - float uv[2]; - float normal[3]; -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - // Contains all Vulkan objects that are required to store and use a texture - // Note that this repository contains a texture class (VulkanTexture.hpp) that encapsulates texture loading functionality in a class that is used in subsequent demos - struct Texture { - VkSampler sampler{ VK_NULL_HANDLE }; - VkImage image{ VK_NULL_HANDLE }; - VkImageLayout imageLayout; - VkDeviceMemory deviceMemory{ VK_NULL_HANDLE }; - VkImageView view{ VK_NULL_HANDLE }; - uint32_t width{ 0 }; - uint32_t height{ 0 }; - uint32_t mipLevels{ 0 }; - } texture; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount{ 0 }; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 viewPos; - // This is used to change the bias for the level-of-detail (mips) in the fragment shader - float lodBias = 0.0f; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Texture loading"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -2.5f)); - camera.setRotation(glm::vec3(0.0f, 15.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - destroyTextureImage(texture); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vertexBuffer.destroy(); - indexBuffer.destroy(); - uniformBuffer.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Enable anisotropic filtering if supported - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - }; - } - - /* - Upload texture image data to the GPU - - Vulkan offers two types of image tiling (memory layout): - - Linear tiled images: - These are stored as is and can be copied directly to. But due to the linear nature they're not a good match for GPUs and format and feature support is very limited. - It's not advised to use linear tiled images for anything else than copying from host to GPU if buffer copies are not an option. - Linear tiling is thus only implemented for learning purposes, one should always prefer optimal tiled image. - - Optimal tiled images: - These are stored in an implementation specific layout matching the capability of the hardware. They usually support more formats and features and are much faster. - Optimal tiled images are stored on the device and not accessible by the host. So they can't be written directly to (like liner tiled images) and always require - some sort of data copy, either from a buffer or a linear tiled image. - - In Short: Always use optimal tiled images for rendering. - */ - void loadTexture() - { - // We use the Khronos texture format (https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/) - std::string filename = getAssetPath() + "textures/metalplate01_rgba.ktx"; - // Texture data contains 4 channels (RGBA) with unnormalized 8-bit values, this is the most commonly supported format - VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; - - ktxResult result; - ktxTexture* ktxTexture; - -#if defined(__ANDROID__) - // Textures are stored inside the apk on Android (compressed) - // So they need to be loaded via the asset manager - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); - if (!asset) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - size_t size = AAsset_getLength(asset); - assert(size > 0); - - ktx_uint8_t *textureData = new ktx_uint8_t[size]; - AAsset_read(asset, textureData, size); - AAsset_close(asset); - result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); - delete[] textureData; -#else - if (!vks::tools::fileExists(filename)) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); -#endif - assert(result == KTX_SUCCESS); - - // Get properties required for using and upload texture data from the ktx texture object - texture.width = ktxTexture->baseWidth; - texture.height = ktxTexture->baseHeight; - texture.mipLevels = ktxTexture->numLevels; - ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); - ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture); - - // We prefer using staging to copy the texture data to a device local optimal image - VkBool32 useStaging = true; - - // Only use linear tiling if forced - bool forceLinearTiling = false; - if (forceLinearTiling) { - // Don't use linear if format is not supported for (linear) shader sampling - // Get device properties for the requested texture format - VkFormatProperties formatProperties; - vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties); - useStaging = !(formatProperties.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); - } - - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs = {}; - - if (useStaging) { - // Copy data to an optimal tiled image - // This loads the texture data into a host local buffer that is copied to the optimal tiled image on the device - - // Create a host-visible staging buffer that contains the raw image data - // This buffer will be the data source for copying texture data to the optimal tiled image on the device - VkBuffer stagingBuffer; - VkDeviceMemory stagingMemory; - - VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = ktxTextureSize; - // This buffer is used as a transfer source for the buffer copy - bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer)); - - // Get memory requirements for the staging buffer (alignment, memory type bits) - vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - // Get memory type index for a host visible buffer - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0)); - - // Copy texture data into host local staging buffer - uint8_t *data; - VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data)); - memcpy(data, ktxTextureData, ktxTextureSize); - vkUnmapMemory(device, stagingMemory); - - // Setup buffer copy regions for each mip level - std::vector bufferCopyRegions; - uint32_t offset = 0; - - for (uint32_t i = 0; i < texture.mipLevels; i++) { - // Calculate offset into staging buffer for the current mip level - ktx_size_t offset; - KTX_error_code ret = ktxTexture_GetImageOffset(ktxTexture, i, 0, 0, &offset); - assert(ret == KTX_SUCCESS); - // Setup a buffer image copy structure for the current mip level - VkBufferImageCopy bufferCopyRegion = {}; - bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - bufferCopyRegion.imageSubresource.mipLevel = i; - bufferCopyRegion.imageSubresource.baseArrayLayer = 0; - bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> i; - bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> i; - bufferCopyRegion.imageExtent.depth = 1; - bufferCopyRegion.bufferOffset = offset; - bufferCopyRegions.push_back(bufferCopyRegion); - } - - // Create optimal tiled target image on the device - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.mipLevels = texture.mipLevels; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - // Set initial layout of the image to undefined - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.extent = { texture.width, texture.height, 1 }; - imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &texture.image)); - - vkGetImageMemoryRequirements(device, texture.image, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &texture.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, texture.image, texture.deviceMemory, 0)); - - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // Image memory barriers for the texture image - - // The sub resource range describes the regions of the image that will be transitioned using the memory barriers below - VkImageSubresourceRange subresourceRange = {}; - // Image only contains color data - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - // Start at first mip level - subresourceRange.baseMipLevel = 0; - // We will transition on all mip levels - subresourceRange.levelCount = texture.mipLevels; - // The 2D texture only has one layer - subresourceRange.layerCount = 1; - - // Transition the texture image layout to transfer target, so we can safely copy our buffer data to it. - VkImageMemoryBarrier imageMemoryBarrier = vks::initializers::imageMemoryBarrier();; - imageMemoryBarrier.image = texture.image; - imageMemoryBarrier.subresourceRange = subresourceRange; - imageMemoryBarrier.srcAccessMask = 0; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - - // Insert a memory dependency at the proper pipeline stages that will execute the image layout transition - // Source pipeline stage is host write/read execution (VK_PIPELINE_STAGE_HOST_BIT) - // Destination pipeline stage is copy command execution (VK_PIPELINE_STAGE_TRANSFER_BIT) - vkCmdPipelineBarrier( - copyCmd, - VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); - - // Copy mip levels from staging buffer - vkCmdCopyBufferToImage( - copyCmd, - stagingBuffer, - texture.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - static_cast(bufferCopyRegions.size()), - bufferCopyRegions.data()); - - // Once the data has been uploaded we transfer to the texture image to the shader read layout, so it can be sampled from - imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - // Insert a memory dependency at the proper pipeline stages that will execute the image layout transition - // Source pipeline stage is copy command execution (VK_PIPELINE_STAGE_TRANSFER_BIT) - // Destination pipeline stage fragment shader access (VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) - vkCmdPipelineBarrier( - copyCmd, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - 0, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); - - // Store current layout for later reuse - texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - // Clean up staging resources - vkFreeMemory(device, stagingMemory, nullptr); - vkDestroyBuffer(device, stagingBuffer, nullptr); - } else { - // Copy data to a linear tiled image - - VkImage mappableImage; - VkDeviceMemory mappableMemory; - - // Load mip map level 0 to linear tiling image - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; - imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - imageCreateInfo.extent = { texture.width, texture.height, 1 }; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &mappableImage)); - - // Get memory requirements for this image like size and alignment - vkGetImageMemoryRequirements(device, mappableImage, &memReqs); - // Set memory allocation size to required memory size - memAllocInfo.allocationSize = memReqs.size; - // Get memory type that can be mapped to host memory - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &mappableMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, mappableImage, mappableMemory, 0)); - - // Map image memory - void *data; - VK_CHECK_RESULT(vkMapMemory(device, mappableMemory, 0, memReqs.size, 0, &data)); - // Copy image data of the first mip level into memory - memcpy(data, ktxTextureData, memReqs.size); - vkUnmapMemory(device, mappableMemory); - - // Linear tiled images don't need to be staged and can be directly used as textures - texture.image = mappableImage; - texture.deviceMemory = mappableMemory; - texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - // Setup image memory barrier transfer image to shader read layout - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // The sub resource range describes the regions of the image we will be transition - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = 1; - subresourceRange.layerCount = 1; - - // Transition the texture image layout to shader read, so it can be sampled from - VkImageMemoryBarrier imageMemoryBarrier = vks::initializers::imageMemoryBarrier();; - imageMemoryBarrier.image = texture.image; - imageMemoryBarrier.subresourceRange = subresourceRange; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - // Insert a memory dependency at the proper pipeline stages that will execute the image layout transition - // Source pipeline stage is host write/read execution (VK_PIPELINE_STAGE_HOST_BIT) - // Destination pipeline stage fragment shader access (VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) - vkCmdPipelineBarrier( - copyCmd, - VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - 0, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - } - - ktxTexture_Destroy(ktxTexture); - - // Create a texture sampler - // In Vulkan textures are accessed by samplers - // This separates all the sampling information from the texture data. This means you could have multiple sampler objects for the same texture with different settings - // Note: Similar to the samplers available with OpenGL 3.3 - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler.mipLodBias = 0.0f; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - // Set max level-of-detail to mip level count of the texture - sampler.maxLod = (useStaging) ? (float)texture.mipLevels : 0.0f; - // Enable anisotropic filtering - // This feature is optional, so we must check if it's supported on the device - if (vulkanDevice->features.samplerAnisotropy) { - // Use max. level of anisotropy for this example - sampler.maxAnisotropy = vulkanDevice->properties.limits.maxSamplerAnisotropy; - sampler.anisotropyEnable = VK_TRUE; - } else { - // The device does not support anisotropic filtering - sampler.maxAnisotropy = 1.0; - sampler.anisotropyEnable = VK_FALSE; - } - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &texture.sampler)); - - // Create image view - // Textures are not directly accessed by the shaders and - // are abstracted by image views containing additional - // information and sub resource ranges - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.format = format; - // The subresource range describes the set of mip levels (and array layers) that can be accessed through this image view - // It's possible to create multiple image views for a single image referring to different (and/or overlapping) ranges of the image - view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view.subresourceRange.baseMipLevel = 0; - view.subresourceRange.baseArrayLayer = 0; - view.subresourceRange.layerCount = 1; - // Linear tiling usually won't support mip maps - // Only set mip map count if optimal tiling is used - view.subresourceRange.levelCount = (useStaging) ? texture.mipLevels : 1; - // The view will be based on the texture's image - view.image = texture.image; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &texture.view)); - } - - // Free all Vulkan resources used by a texture object - void destroyTextureImage(Texture texture) - { - vkDestroyImageView(device, texture.view, nullptr); - vkDestroyImage(device, texture.image, nullptr); - vkDestroySampler(device, texture.sampler, nullptr); - vkFreeMemory(device, texture.deviceMemory, nullptr); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &vertexBuffer.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); - - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - // Creates a vertex and index buffer for a quad made of two triangles - // This is used to display the texture on - void generateQuad() - { - // Setup vertices for a single uv-mapped quad made from two triangles - std::vector vertices = - { - { { 1.0f, 1.0f, 0.0f }, { 1.0f, 1.0f },{ 0.0f, 0.0f, 1.0f } }, - { { -1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f },{ 0.0f, 0.0f, 1.0f } }, - { { -1.0f, -1.0f, 0.0f }, { 0.0f, 0.0f },{ 0.0f, 0.0f, 1.0f } }, - { { 1.0f, -1.0f, 0.0f }, { 1.0f, 0.0f },{ 0.0f, 0.0f, 1.0f } } - }; - - // Setup indices - std::vector indices = { 0,1,2, 2,3,0 }; - indexCount = static_cast(indices.size()); - - // Create buffers and upload data to the GPU - struct StagingBuffers { - vks::Buffer vertices; - vks::Buffer indices; - } stagingBuffers; - - // Host visible source buffers (staging) - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.vertices, vertices.size() * sizeof(Vertex), vertices.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.indices, indices.size() * sizeof(uint32_t), indices.data())); - - // Device local destination buffers - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &vertexBuffer, vertices.size() * sizeof(Vertex))); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &indexBuffer, indices.size() * sizeof(uint32_t))); - - // Copy from host do device - vulkanDevice->copyBuffer(&stagingBuffers.vertices, &vertexBuffer, queue); - vulkanDevice->copyBuffer(&stagingBuffers.indices, &indexBuffer, queue); - - // Clean up - stagingBuffers.vertices.destroy(); - stagingBuffers.indices.destroy(); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - // The sample uses a combined image + sampler descriptor to sample the texture in the fragment shader - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - // Setup a descriptor image info for the current texture to be used as a combined image sampler - VkDescriptorImageInfo textureDescriptor; - // The image's view (images are never directly accessed by the shader, but rather through views defining subresources) - textureDescriptor.imageView = texture.view; - // The sampler (Telling the pipeline how to sample the texture, including repeat, border, etc.) - textureDescriptor.sampler = texture.sampler; - // The current layout of the image(Note: Should always fit the actual use, e.g.shader read) - textureDescriptor.imageLayout = texture.imageLayout; - - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Fragment shader texture sampler - // Fragment shader: layout (binding = 1) uniform sampler2D samplerColor; - vks::initializers::writeDescriptorSet(descriptorSet, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // The descriptor set will use a combined image sampler (as opposed to splitting image and sampler) - 1, // Shader binding point 1 - &textureDescriptor) // Pointer to the descriptor image for our texture - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Shaders - shaderStages[0] = loadShader(getShadersPath() + "texture/texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "texture/texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - // Vertex input state - std::vector vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX) - }; - std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)), - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)), - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal)), - }; - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &vertexInputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(uniformData), &uniformData)); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - uniformData.viewPos = camera.viewPos; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadTexture(); - generateQuad(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->sliderFloat("LOD bias", &uniformData.lodBias, 0.0f, (float)texture.mipLevels)) { - updateUniformBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/texture3d/texture3d.cpp b/examples/texture3d/texture3d.cpp deleted file mode 100644 index b42a037e..00000000 --- a/examples/texture3d/texture3d.cpp +++ /dev/null @@ -1,651 +0,0 @@ -/* -* Vulkan Example - 3D texture loading (and generation using perlin noise) example -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -// Vertex layout for this example -struct Vertex { - float pos[3]; - float uv[2]; - float normal[3]; -}; - -// Translation of Ken Perlin's JAVA implementation (http://mrl.nyu.edu/~perlin/noise/) -template -class PerlinNoise -{ -private: - uint32_t permutations[512]; - T fade(T t) - { - return t * t * t * (t * (t * (T)6 - (T)15) + (T)10); - } - T lerp(T t, T a, T b) - { - return a + t * (b - a); - } - T grad(int hash, T x, T y, T z) - { - // Convert LO 4 bits of hash code into 12 gradient directions - int h = hash & 15; - T u = h < 8 ? x : y; - T v = h < 4 ? y : h == 12 || h == 14 ? x : z; - return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); - } -public: - PerlinNoise(bool applyRandomSeed) - { - // Generate random lookup for permutations containing all numbers from 0..255 - std::vector plookup; - plookup.resize(256); - std::iota(plookup.begin(), plookup.end(), 0); - std::default_random_engine rndEngine(applyRandomSeed ? std::random_device{}() : 0); - std::shuffle(plookup.begin(), plookup.end(), rndEngine); - - for (uint32_t i = 0; i < 256; i++) - { - permutations[i] = permutations[256 + i] = plookup[i]; - } - } - T noise(T x, T y, T z) - { - // Find unit cube that contains point - int32_t X = (int32_t)floor(x) & 255; - int32_t Y = (int32_t)floor(y) & 255; - int32_t Z = (int32_t)floor(z) & 255; - // Find relative x,y,z of point in cube - x -= floor(x); - y -= floor(y); - z -= floor(z); - - // Compute fade curves for each of x,y,z - T u = fade(x); - T v = fade(y); - T w = fade(z); - - // Hash coordinates of the 8 cube corners - uint32_t A = permutations[X] + Y; - uint32_t AA = permutations[A] + Z; - uint32_t AB = permutations[A + 1] + Z; - uint32_t B = permutations[X + 1] + Y; - uint32_t BA = permutations[B] + Z; - uint32_t BB = permutations[B + 1] + Z; - - // And add blended results for 8 corners of the cube; - T res = lerp(w, lerp(v, - lerp(u, grad(permutations[AA], x, y, z), grad(permutations[BA], x - 1, y, z)), lerp(u, grad(permutations[AB], x, y - 1, z), grad(permutations[BB], x - 1, y - 1, z))), - lerp(v, lerp(u, grad(permutations[AA + 1], x, y, z - 1), grad(permutations[BA + 1], x - 1, y, z - 1)), lerp(u, grad(permutations[AB + 1], x, y - 1, z - 1), grad(permutations[BB + 1], x - 1, y - 1, z - 1)))); - return res; - } -}; - -// Fractal noise generator based on perlin noise above -template -class FractalNoise -{ -private: - PerlinNoise perlinNoise; - uint32_t octaves; - T frequency; - T amplitude; - T persistence; -public: - FractalNoise(const PerlinNoise &perlinNoiseIn) : - perlinNoise(perlinNoiseIn) - { - octaves = 6; - persistence = (T)0.5; - } - - T noise(T x, T y, T z) - { - T sum = 0; - T frequency = (T)1; - T amplitude = (T)1; - T max = (T)0; - for (uint32_t i = 0; i < octaves; i++) - { - sum += perlinNoise.noise(x * frequency, y * frequency, z * frequency) * amplitude; - max += amplitude; - amplitude *= persistence; - frequency *= (T)2; - } - - sum = sum / max; - return (sum + (T)1.0) / (T)2.0; - } -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - // Contains all Vulkan objects that are required to store and use a 3D texture - struct Texture { - VkSampler sampler = VK_NULL_HANDLE; - VkImage image = VK_NULL_HANDLE; - VkImageLayout imageLayout; - VkDeviceMemory deviceMemory = VK_NULL_HANDLE; - VkImageView view = VK_NULL_HANDLE; - VkDescriptorImageInfo descriptor; - VkFormat format; - uint32_t width{ 0 }; - uint32_t height{ 0 }; - uint32_t depth{ 0 }; - uint32_t mipLevels{ 0 }; - } texture; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount{ 0 }; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::vec4 viewPos; - // The current depth level of the texture to display - // This is animated - float depth = 0.0f; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "3D textures"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -2.5f)); - camera.setRotation(glm::vec3(0.0f, 15.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - srand(benchmark.active ? 0 : (unsigned int)time(NULL)); - } - - ~VulkanExample() - { - if (device) { - destroyTextureImage(texture); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vertexBuffer.destroy(); - indexBuffer.destroy(); - uniformBuffer.destroy(); - } - } - - // Prepare all Vulkan resources for the 3D texture (including descriptors) - // Does not fill the texture with data - void prepareNoiseTexture(uint32_t width, uint32_t height, uint32_t depth) - { - // A 3D texture is described as width x height x depth - texture.width = width; - texture.height = height; - texture.depth = depth; - texture.mipLevels = 1; - texture.format = VK_FORMAT_R8_UNORM; - - // Format support check - // 3D texture support in Vulkan is mandatory (in contrast to OpenGL) so no need to check if it's supported - VkFormatProperties formatProperties; - vkGetPhysicalDeviceFormatProperties(physicalDevice, texture.format, &formatProperties); - // Check if format supports transfer - if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) - { - std::cout << "Error: Device does not support flag TRANSFER_DST for selected texture format!" << std::endl; - return; - } - // Check if GPU supports requested 3D texture dimensions - uint32_t maxImageDimension3D(vulkanDevice->properties.limits.maxImageDimension3D); - if (width > maxImageDimension3D || height > maxImageDimension3D || depth > maxImageDimension3D) - { - std::cout << "Error: Requested texture dimensions is greater than supported 3D texture dimension!" << std::endl; - return; - } - - // Create optimal tiled target image - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_3D; - imageCreateInfo.format = texture.format; - imageCreateInfo.mipLevels = texture.mipLevels; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCreateInfo.extent.width = texture.width; - imageCreateInfo.extent.height = texture.height; - imageCreateInfo.extent.depth = texture.depth; - // Set initial layout of the image to undefined - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &texture.image)); - - // Device local memory to back up image - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs = {}; - vkGetImageMemoryRequirements(device, texture.image, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &texture.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, texture.image, texture.deviceMemory, 0)); - - // Create sampler - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.mipLodBias = 0.0f; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = 0.0f; - sampler.maxAnisotropy = 1.0; - sampler.anisotropyEnable = VK_FALSE; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &texture.sampler)); - - // Create image view - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.image = texture.image; - view.viewType = VK_IMAGE_VIEW_TYPE_3D; - view.format = texture.format; - view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view.subresourceRange.baseMipLevel = 0; - view.subresourceRange.baseArrayLayer = 0; - view.subresourceRange.layerCount = 1; - view.subresourceRange.levelCount = 1; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &texture.view)); - - // Fill image descriptor image info to be used descriptor set setup - texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - texture.descriptor.imageView = texture.view; - texture.descriptor.sampler = texture.sampler; - - updateNoiseTexture(); - } - - // Generate randomized noise and upload it to the 3D texture using staging - void updateNoiseTexture() - { - const uint32_t texMemSize = texture.width * texture.height * texture.depth; - - uint8_t *data = new uint8_t[texMemSize]; - memset(data, 0, texMemSize); - - // Generate perlin based noise - std::cout << "Generating " << texture.width << " x " << texture.height << " x " << texture.depth << " noise texture..." << std::endl; - - auto tStart = std::chrono::high_resolution_clock::now(); - - PerlinNoise perlinNoise(!benchmark.active); - FractalNoise fractalNoise(perlinNoise); - - const float noiseScale = static_cast(rand() % 10) + 4.0f; - -#pragma omp parallel for - for (int32_t z = 0; z < static_cast(texture.depth); z++) - { - for (int32_t y = 0; y < static_cast(texture.height); y++) - { - for (int32_t x = 0; x < static_cast(texture.width); x++) - { - float nx = (float)x / (float)texture.width; - float ny = (float)y / (float)texture.height; - float nz = (float)z / (float)texture.depth; - float n = fractalNoise.noise(nx * noiseScale, ny * noiseScale, nz * noiseScale); - n = n - floor(n); - data[x + y * texture.width + z * texture.width * texture.height] = static_cast(floor(n * 255)); - } - } - } - - auto tEnd = std::chrono::high_resolution_clock::now(); - auto tDiff = std::chrono::duration(tEnd - tStart).count(); - - std::cout << "Done in " << tDiff << "ms" << std::endl; - - // Create a host-visible staging buffer that contains the raw image data - VkBuffer stagingBuffer; - VkDeviceMemory stagingMemory; - - // Buffer object - VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = texMemSize; - bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer)); - - // Allocate host visible memory for data upload - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs = {}; - vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0)); - - // Copy texture data into staging buffer - uint8_t *mapped; - VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&mapped)); - memcpy(mapped, data, texMemSize); - vkUnmapMemory(device, stagingMemory); - - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // The sub resource range describes the regions of the image we will be transitioned - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = 1; - subresourceRange.layerCount = 1; - - // Optimal image will be used as destination for the copy, so we must transfer from our - // initial undefined image layout to the transfer destination layout - vks::tools::setImageLayout( - copyCmd, - texture.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Copy 3D noise data to texture - - // Setup buffer copy regions - VkBufferImageCopy bufferCopyRegion{}; - bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - bufferCopyRegion.imageSubresource.mipLevel = 0; - bufferCopyRegion.imageSubresource.baseArrayLayer = 0; - bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = texture.width; - bufferCopyRegion.imageExtent.height = texture.height; - bufferCopyRegion.imageExtent.depth = texture.depth; - - vkCmdCopyBufferToImage( - copyCmd, - stagingBuffer, - texture.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &bufferCopyRegion); - - // Change texture image layout to shader read after all mip levels have been copied - texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vks::tools::setImageLayout( - copyCmd, - texture.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - texture.imageLayout, - subresourceRange); - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - // Clean up staging resources - delete[] data; - vkFreeMemory(device, stagingMemory, nullptr); - vkDestroyBuffer(device, stagingBuffer, nullptr); - } - - // Free all Vulkan resources used a texture object - void destroyTextureImage(Texture texture) - { - if (texture.view != VK_NULL_HANDLE) - vkDestroyImageView(device, texture.view, nullptr); - if (texture.image != VK_NULL_HANDLE) - vkDestroyImage(device, texture.image, nullptr); - if (texture.sampler != VK_NULL_HANDLE) - vkDestroySampler(device, texture.sampler, nullptr); - if (texture.deviceMemory != VK_NULL_HANDLE) - vkFreeMemory(device, texture.deviceMemory, nullptr); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &vertexBuffer.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - // Creates a vertex and index buffer for a quad made of two triangles - // This is used to display the texture on - void generateQuad() - { - // Setup vertices for a single uv-mapped quad made from two triangles - std::vector vertices = - { - { { 1.0f, 1.0f, 0.0f }, { 1.0f, 1.0f },{ 0.0f, 0.0f, 1.0f } }, - { { -1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f },{ 0.0f, 0.0f, 1.0f } }, - { { -1.0f, -1.0f, 0.0f }, { 0.0f, 0.0f },{ 0.0f, 0.0f, 1.0f } }, - { { 1.0f, -1.0f, 0.0f }, { 1.0f, 0.0f },{ 0.0f, 0.0f, 1.0f } } - }; - - // Setup indices - std::vector indices = { 0,1,2, 2,3,0 }; - indexCount = static_cast(indices.size()); - - // Create buffers and upload data to the GPU - struct StagingBuffers { - vks::Buffer vertices; - vks::Buffer indices; - } stagingBuffers; - - // Host visible source buffers (staging) - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.vertices, vertices.size() * sizeof(Vertex), vertices.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.indices, indices.size() * sizeof(uint32_t), indices.data())); - - // Device local destination buffers - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &vertexBuffer, vertices.size() * sizeof(Vertex))); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &indexBuffer, indices.size() * sizeof(uint32_t))); - - // Copy from host do device - vulkanDevice->copyBuffer(&stagingBuffers.vertices, &vertexBuffer, queue); - vulkanDevice->copyBuffer(&stagingBuffers.indices, &indexBuffer, queue); - - // Clean up - stagingBuffers.vertices.destroy(); - stagingBuffers.indices.destroy(); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - // Image descriptor for the 3D texture - VkDescriptorImageInfo textureDescriptor = - vks::initializers::descriptorImageInfo( - texture.sampler, - texture.view, - texture.imageLayout); - - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Fragment shader texture sampler - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textureDescriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Shaders - shaderStages[0] = loadShader(getShadersPath() + "texture3d/texture3d.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "texture3d/texture3d.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - // Vertex input state - std::vector vertexInputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX) - }; - std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)), - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)), - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal)), - }; - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &vertexInputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData), &uniformData)); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - uniformData.viewPos = camera.viewPos; - if (!paused) { - // Animate depth - uniformData.depth += frameTimer * 0.15f; - if (uniformData.depth > 1.0f) { - uniformData.depth = uniformData.depth - 1.0f; - } - } - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - generateQuad(); - prepareUniformBuffers(); - prepareNoiseTexture(128, 128, 128); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->button("Generate new texture")) { - updateNoiseTexture(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/texturearray/texturearray.cpp b/examples/texturearray/texturearray.cpp deleted file mode 100644 index ca7e2c59..00000000 --- a/examples/texturearray/texturearray.cpp +++ /dev/null @@ -1,544 +0,0 @@ -/* -* Vulkan Example - Texture arrays and instanced rendering -* -* This sample shows how to load and render a texture array. This is a single layered texture where each layer contains different image data. -* The different layers are displayed on cubes using instancing, where each instance selects a different layer from the texture -* -* Copyright (C) 2016-2023 Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include -#include - -#define MAX_LAYERS 8 - -// Vertex layout for this example -struct Vertex { - float pos[3]; - float uv[2]; -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - // Number of array layers in texture array - // Also used as instance count - uint32_t layerCount{ 0 }; - vks::Texture textureArray; - - vks::Buffer vertexBuffer; - vks::Buffer indexBuffer; - uint32_t indexCount{ 0 }; - - // Values passed to the shader per drawn instance - struct alignas(16) PerInstanceData { - // Model matrix - glm::mat4 model; - // Layer index from which this instance will sample in the fragment shader - float arrayIndex{ 0 }; - }; - - struct UniformData { - // Global matrices - struct { - glm::mat4 projection; - glm::mat4 view; - } matrices; - // Separate data for each instance - PerInstanceData* instance{ nullptr }; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Texture arrays"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -7.5f)); - camera.setRotation(glm::vec3(-35.0f, 0.0f, 0.0f)); - camera.setPerspective(45.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyImageView(device, textureArray.view, nullptr); - vkDestroyImage(device, textureArray.image, nullptr); - vkDestroySampler(device, textureArray.sampler, nullptr); - vkFreeMemory(device, textureArray.deviceMemory, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vertexBuffer.destroy(); - indexBuffer.destroy(); - uniformBuffer.destroy(); - delete[] uniformData.instance; - } - } - - void loadTextureArray(std::string filename, VkFormat format) - { - ktxResult result; - ktxTexture* ktxTexture; - -#if defined(__ANDROID__) - // Textures are stored inside the apk on Android (compressed) - // So they need to be loaded via the asset manager - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); - if (!asset) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - size_t size = AAsset_getLength(asset); - assert(size > 0); - - ktx_uint8_t *textureData = new ktx_uint8_t[size]; - AAsset_read(asset, textureData, size); - AAsset_close(asset); - result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); - delete[] textureData; -#else - if (!vks::tools::fileExists(filename)) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); -#endif - assert(result == KTX_SUCCESS); - - // Get properties required for using and upload texture data from the ktx texture object - textureArray.width = ktxTexture->baseWidth; - textureArray.height = ktxTexture->baseHeight; - layerCount = ktxTexture->numLayers; - assert(layerCount <= MAX_LAYERS); - ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); - ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture); - - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - // Create a host-visible staging buffer that contains the raw image data - VkBuffer stagingBuffer; - VkDeviceMemory stagingMemory; - - VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = ktxTextureSize; - // This buffer is used as a transfer source for the buffer copy - bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer)); - - // Get memory requirements for the staging buffer (alignment, memory type bits) - vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); - - memAllocInfo.allocationSize = memReqs.size; - // Get memory type index for a host visible buffer - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0)); - - // Copy texture data into staging buffer - uint8_t *data; - VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data)); - memcpy(data, ktxTextureData, ktxTextureSize); - vkUnmapMemory(device, stagingMemory); - - // Setup buffer copy regions for array layers - std::vector bufferCopyRegions; - - // To keep this simple, we will only load layers and no mip level - for (uint32_t layer = 0; layer < layerCount; layer++) - { - // Calculate offset into staging buffer for the current array layer - ktx_size_t offset; - KTX_error_code ret = ktxTexture_GetImageOffset(ktxTexture, 0, layer, 0, &offset); - assert(ret == KTX_SUCCESS); - // Setup a buffer image copy structure for the current array layer - VkBufferImageCopy bufferCopyRegion = {}; - bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - bufferCopyRegion.imageSubresource.mipLevel = 0; - bufferCopyRegion.imageSubresource.baseArrayLayer = layer; - bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth; - bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight; - bufferCopyRegion.imageExtent.depth = 1; - bufferCopyRegion.bufferOffset = offset; - bufferCopyRegions.push_back(bufferCopyRegion); - } - - // Create optimal tiled target image - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.extent = { textureArray.width, textureArray.height, 1 }; - imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - imageCreateInfo.arrayLayers = layerCount; - - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &textureArray.image)); - - vkGetImageMemoryRequirements(device, textureArray.image, &memReqs); - - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &textureArray.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, textureArray.image, textureArray.deviceMemory, 0)); - - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // Image barrier for optimal image (target) - // Set initial layout for all array layers (faces) of the optimal (target) tiled texture - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = 1; - subresourceRange.layerCount = layerCount; - - vks::tools::setImageLayout( - copyCmd, - textureArray.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Copy the cube map faces from the staging buffer to the optimal tiled image - vkCmdCopyBufferToImage( - copyCmd, - stagingBuffer, - textureArray.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - static_cast(bufferCopyRegions.size()), - bufferCopyRegions.data()); - - // Change texture image layout to shader read after all faces have been copied - textureArray.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vks::tools::setImageLayout( - copyCmd, - textureArray.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - textureArray.imageLayout, - subresourceRange); - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - // Create sampler - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 8; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = 0.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &textureArray.sampler)); - - // Create image view - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - view.format = format; - view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - view.subresourceRange.layerCount = layerCount; - view.subresourceRange.levelCount = 1; - view.image = textureArray.image; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &textureArray.view)); - - // Clean up staging resources - vkFreeMemory(device, stagingMemory, nullptr); - vkDestroyBuffer(device, stagingBuffer, nullptr); - ktxTexture_Destroy(ktxTexture); - } - - void loadAssets() - { - loadTextureArray(getAssetPath() + "textures/texturearray_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &vertexBuffer.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); - - vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, layerCount, 0, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - // Creates a vertex and index buffer for a cube - // This is used to display the texture on - void generateCube() - { - std::vector vertices = { - { { -1.0f, -1.0f, 1.0f }, { 0.0f, 0.0f } }, - { { 1.0f, -1.0f, 1.0f }, { 1.0f, 0.0f } }, - { { 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f } }, - { { -1.0f, 1.0f, 1.0f }, { 0.0f, 1.0f } }, - - { { 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f } }, - { { 1.0f, 1.0f, -1.0f }, { 1.0f, 0.0f } }, - { { 1.0f, -1.0f, -1.0f }, { 1.0f, 1.0f } }, - { { 1.0f, -1.0f, 1.0f }, { 0.0f, 1.0f } }, - - { { -1.0f, -1.0f, -1.0f }, { 0.0f, 0.0f } }, - { { 1.0f, -1.0f, -1.0f }, { 1.0f, 0.0f } }, - { { 1.0f, 1.0f, -1.0f }, { 1.0f, 1.0f } }, - { { -1.0f, 1.0f, -1.0f }, { 0.0f, 1.0f } }, - - { { -1.0f, -1.0f, -1.0f }, { 0.0f, 0.0f } }, - { { -1.0f, -1.0f, 1.0f }, { 1.0f, 0.0f } }, - { { -1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f } }, - { { -1.0f, 1.0f, -1.0f }, { 0.0f, 1.0f } }, - - { { 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f } }, - { { -1.0f, 1.0f, 1.0f }, { 1.0f, 0.0f } }, - { { -1.0f, 1.0f, -1.0f }, { 1.0f, 1.0f } }, - { { 1.0f, 1.0f, -1.0f }, { 0.0f, 1.0f } }, - - { { -1.0f, -1.0f, -1.0f }, { 0.0f, 0.0f } }, - { { 1.0f, -1.0f, -1.0f }, { 1.0f, 0.0f } }, - { { 1.0f, -1.0f, 1.0f }, { 1.0f, 1.0f } }, - { { -1.0f, -1.0f, 1.0f }, { 0.0f, 1.0f } }, - }; - std::vector indices = { - 0,1,2, 0,2,3, 4,5,6, 4,6,7, 8,9,10, 8,10,11, 12,13,14, 12,14,15, 16,17,18, 16,18,19, 20,21,22, 20,22,23 - }; - - indexCount = static_cast(indices.size()); - - // Create buffers and upload data to the GPU - struct StagingBuffers { - vks::Buffer vertices; - vks::Buffer indices; - } stagingBuffers; - - // Host visible source buffers (staging) - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.vertices, vertices.size() * sizeof(Vertex), vertices.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.indices, indices.size() * sizeof(uint32_t), indices.data())); - - // Device local destination buffers - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &vertexBuffer, vertices.size() * sizeof(Vertex))); - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &indexBuffer, indices.size() * sizeof(uint32_t))); - - // Copy from host do device - vulkanDevice->copyBuffer(&stagingBuffers.vertices, &vertexBuffer, queue); - vulkanDevice->copyBuffer(&stagingBuffers.indices, &indexBuffer, queue); - - // Clean up - stagingBuffers.vertices.destroy(); - stagingBuffers.indices.destroy(); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - // Image descriptor for the texture array - VkDescriptorImageInfo textureDescriptor = - vks::initializers::descriptorImageInfo( - textureArray.sampler, - textureArray.view, - textureArray.imageLayout); - - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Fragment shader texture sampler - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textureDescriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables, 0); - - // Vertex bindings and attributes - VkVertexInputBindingDescription vertexInputBinding = { 0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX }; - std::vector vertexInputAttributes = { - { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos) }, - { 1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv) }, - }; - VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputStateCI.vertexBindingDescriptionCount = 1; - vertexInputStateCI.pVertexBindingDescriptions = &vertexInputBinding; - vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); - - // Instancing pipeline - std::array shaderStages; - - shaderStages[0] = loadShader(getShadersPath() + "texturearray/instancing.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "texturearray/instancing.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pVertexInputState = &vertexInputStateCI; - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - void prepareUniformBuffers() - { - uniformData.instance = new PerInstanceData[layerCount]; - - uint32_t uboSize = sizeof(uniformData.matrices) + (MAX_LAYERS * sizeof(PerInstanceData)); - - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, uboSize)); - - // Array indices and model matrices are fixed - float offset = -1.5f; - float center = (layerCount*offset) / 2.0f - (offset * 0.5f); - for (uint32_t i = 0; i < layerCount; i++) { - // Instance model matrix - uniformData.instance[i].model = glm::translate(glm::mat4(1.0f), glm::vec3(i * offset - center, 0.0f, 0.0f)); - uniformData.instance[i].model = glm::scale(uniformData.instance[i].model, glm::vec3(0.5f)); - // Instance texture array index - uniformData.instance[i].arrayIndex = (float)i; - } - - // Update instanced part of the uniform buffer - uint8_t *pData; - uint32_t dataOffset = sizeof(uniformData.matrices); - uint32_t dataSize = layerCount * sizeof(PerInstanceData); - VK_CHECK_RESULT(vkMapMemory(device, uniformBuffer.memory, dataOffset, dataSize, 0, (void **)&pData)); - memcpy(pData, uniformData.instance, dataSize); - vkUnmapMemory(device, uniformBuffer.memory); - - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffersCamera() - { - uniformData.matrices.projection = camera.matrices.perspective; - uniformData.matrices.view = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uniformData.matrices, sizeof(uniformData.matrices)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - generateCube(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffersCamera(); - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/texturecubemap/texturecubemap.cpp b/examples/texturecubemap/texturecubemap.cpp deleted file mode 100644 index c426916d..00000000 --- a/examples/texturecubemap/texturecubemap.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* -* Vulkan Example - Cube map texture loading and displaying -* -* This sample shows how to load and render a cubemap. A cubemap is a textures that contains 6 images, one per cube face. -* The sample displays the cubemap as a skybox (background) and as a reflection on a selectable object -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" -#include -#include - -class VulkanExample : public VulkanExampleBase -{ -public: - bool displaySkybox = true; - - vks::Texture cubeMap; - - struct Models { - vkglTF::Model skybox; - // The sample lets you select different models to apply the cubemap to - std::vector objects; - int32_t objectIndex = 0; - } models; - - struct UBOVS { - glm::mat4 projection; - glm::mat4 modelView; - glm::mat4 inverseModelview; - float lodBias = 0.0f; - } uboVS; - vks::Buffer uniformBuffer; - - struct { - VkPipeline skybox{ VK_NULL_HANDLE }; - VkPipeline reflect{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - std::vector objectNames; - - VulkanExample() : VulkanExampleBase() - { - title = "Cube map textures"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -4.0f)); - camera.setRotation(glm::vec3(0.0f)); - camera.setRotationSpeed(0.25f); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyImageView(device, cubeMap.view, nullptr); - vkDestroyImage(device, cubeMap.image, nullptr); - vkDestroySampler(device, cubeMap.sampler, nullptr); - vkFreeMemory(device, cubeMap.deviceMemory, nullptr); - vkDestroyPipeline(device, pipelines.skybox, nullptr); - vkDestroyPipeline(device, pipelines.reflect, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - } - - // Loads a cubemap from a file, uploads it to the device and create all Vulkan resources required to display it - void loadCubemap(std::string filename, VkFormat format) - { - ktxResult result; - ktxTexture* ktxTexture; - -#if defined(__ANDROID__) - // Textures are stored inside the apk on Android (compressed) - // So they need to be loaded via the asset manager - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); - if (!asset) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - size_t size = AAsset_getLength(asset); - assert(size > 0); - - ktx_uint8_t *textureData = new ktx_uint8_t[size]; - AAsset_read(asset, textureData, size); - AAsset_close(asset); - result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); - delete[] textureData; -#else - if (!vks::tools::fileExists(filename)) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); -#endif - assert(result == KTX_SUCCESS); - - // Get properties required for using and upload texture data from the ktx texture object - cubeMap.width = ktxTexture->baseWidth; - cubeMap.height = ktxTexture->baseHeight; - cubeMap.mipLevels = ktxTexture->numLevels; - ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); - ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture); - - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - // Create a host-visible staging buffer that contains the raw image data - VkBuffer stagingBuffer; - VkDeviceMemory stagingMemory; - - VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = ktxTextureSize; - // This buffer is used as a transfer source for the buffer copy - bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer)); - - // Get memory requirements for the staging buffer (alignment, memory type bits) - vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - // Get memory type index for a host visible buffer - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0)); - - // Copy texture data into staging buffer - uint8_t *data; - VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data)); - memcpy(data, ktxTextureData, ktxTextureSize); - vkUnmapMemory(device, stagingMemory); - - // Create optimal tiled target image - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.mipLevels = cubeMap.mipLevels; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.extent = { cubeMap.width, cubeMap.height, 1 }; - imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - // Cube faces count as array layers in Vulkan - imageCreateInfo.arrayLayers = 6; - // This flag is required for cube map images - imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &cubeMap.image)); - - vkGetImageMemoryRequirements(device, cubeMap.image, &memReqs); - - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &cubeMap.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, cubeMap.image, cubeMap.deviceMemory, 0)); - - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // Setup buffer copy regions for each face including all of its miplevels - std::vector bufferCopyRegions; - uint32_t offset = 0; - - for (uint32_t face = 0; face < 6; face++) - { - for (uint32_t level = 0; level < cubeMap.mipLevels; level++) - { - // Calculate offset into staging buffer for the current mip level and face - ktx_size_t offset; - KTX_error_code ret = ktxTexture_GetImageOffset(ktxTexture, level, 0, face, &offset); - assert(ret == KTX_SUCCESS); - VkBufferImageCopy bufferCopyRegion = {}; - bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - bufferCopyRegion.imageSubresource.mipLevel = level; - bufferCopyRegion.imageSubresource.baseArrayLayer = face; - bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> level; - bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> level; - bufferCopyRegion.imageExtent.depth = 1; - bufferCopyRegion.bufferOffset = offset; - bufferCopyRegions.push_back(bufferCopyRegion); - } - } - - // Image barrier for optimal image (target) - // Set initial layout for all array layers (faces) of the optimal (target) tiled texture - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = cubeMap.mipLevels; - subresourceRange.layerCount = 6; - - vks::tools::setImageLayout( - copyCmd, - cubeMap.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - // Copy the cube map faces from the staging buffer to the optimal tiled image - vkCmdCopyBufferToImage( - copyCmd, - stagingBuffer, - cubeMap.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - static_cast(bufferCopyRegions.size()), - bufferCopyRegions.data() - ); - - // Change texture image layout to shader read after all faces have been copied - cubeMap.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vks::tools::setImageLayout( - copyCmd, - cubeMap.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - cubeMap.imageLayout, - subresourceRange); - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - // Create sampler - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = static_cast(cubeMap.mipLevels); - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - sampler.maxAnisotropy = 1.0f; - if (vulkanDevice->features.samplerAnisotropy) - { - sampler.maxAnisotropy = vulkanDevice->properties.limits.maxSamplerAnisotropy; - sampler.anisotropyEnable = VK_TRUE; - } - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &cubeMap.sampler)); - - // Create image view - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - // Cube map view type - view.viewType = VK_IMAGE_VIEW_TYPE_CUBE; - view.format = format; - view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - // 6 array layers (faces) - view.subresourceRange.layerCount = 6; - // Set number of mip levels - view.subresourceRange.levelCount = cubeMap.mipLevels; - view.image = cubeMap.image; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &cubeMap.view)); - - // Clean up staging resources - vkFreeMemory(device, stagingMemory, nullptr); - vkDestroyBuffer(device, stagingBuffer, nullptr); - ktxTexture_Destroy(ktxTexture); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - // Skybox - if (displaySkybox) - { - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skybox); - models.skybox.draw(drawCmdBuffers[i]); - } - - // 3D object - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.reflect); - models.objects[models.objectIndex].draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY; - // Skybox - models.skybox.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - // Objects - std::vector filenames = { "sphere.gltf", "teapot.gltf", "torusknot.gltf", "venus.gltf" }; - objectNames = { "Sphere", "Teapot", "Torusknot", "Venus" }; - models.objects.resize(filenames.size()); - for (size_t i = 0; i < filenames.size(); i++) { - models.objects[i].loadFromFile(getAssetPath() + "models/" + filenames[i], vulkanDevice, queue, glTFLoadingFlags); - } - // Cubemap texture - loadCubemap(getAssetPath() + "textures/cubemap_yokohama_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - // Image descriptor for the cube map texture - VkDescriptorImageInfo textureDescriptor = vks::initializers::descriptorImageInfo(cubeMap.sampler, cubeMap.view, cubeMap.imageLayout); - - std::vector writeDescriptorSets = - { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Fragment shader cubemap sampler - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textureDescriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - const VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal }); - - // Skybox pipeline (background cube) - shaderStages[0] = loadShader(getShadersPath() + "texturecubemap/skybox.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "texturecubemap/skybox.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.skybox)); - - // Cube map reflect pipeline - shaderStages[0] = loadShader(getShadersPath() + "texturecubemap/reflect.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "texturecubemap/reflect.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Enable depth test and write - depthStencilState.depthWriteEnable = VK_TRUE; - depthStencilState.depthTestEnable = VK_TRUE; - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.reflect)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(uboVS))); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uboVS.projection = camera.matrices.perspective; - // Note: Both the object and skybox use the same uniform data, the translation part of the skybox is removed in the shader (see skybox.vert) - uboVS.modelView = camera.matrices.view; - uboVS.inverseModelview = glm::inverse(camera.matrices.view); - memcpy(uniformBuffer.mapped, &uboVS, sizeof(uboVS)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->sliderFloat("LOD bias", &uboVS.lodBias, 0.0f, (float)cubeMap.mipLevels)) { - updateUniformBuffers(); - } - if (overlay->comboBox("Object type", &models.objectIndex, objectNames)) { - buildCommandBuffers(); - } - if (overlay->checkBox("Skybox", &displaySkybox)) { - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/texturecubemaparray/texturecubemaparray.cpp b/examples/texturecubemaparray/texturecubemaparray.cpp deleted file mode 100644 index a8826d09..00000000 --- a/examples/texturecubemaparray/texturecubemaparray.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* -* Vulkan Example - Cube map array texture loading and displaying -* -* This sample shows how load and render an cubemap array texture. A single image contains multiple cube maps. -* The cubemap to be displayed is selected in the fragment shader -* -* Copyright (C) 2020-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" -#include -#include - -class VulkanExample : public VulkanExampleBase -{ -public: - bool displaySkybox = true; - - vks::Texture cubeMapArray; - - struct Meshes { - vkglTF::Model skybox; - std::vector objects; - int32_t objectIndex = 0; - } models; - - struct UniformData { - glm::mat4 projection; - glm::mat4 modelView; - glm::mat4 inverseModelview; - float lodBias = 0.0f; - // Used by the fragment shader to select the cubemap from the array cubemap - int cubeMapIndex = 1; - } uniformData; - vks::Buffer uniformBuffer; - - struct { - VkPipeline skybox{ VK_NULL_HANDLE }; - VkPipeline reflect{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - std::vector objectNames; - - VulkanExample() : VulkanExampleBase() - { - title = "Cube map texture arrays"; - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -4.0f)); - camera.setRotationSpeed(0.25f); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyImageView(device, cubeMapArray.view, nullptr); - vkDestroyImage(device, cubeMapArray.image, nullptr); - vkDestroySampler(device, cubeMapArray.sampler, nullptr); - vkFreeMemory(device, cubeMapArray.deviceMemory, nullptr); - vkDestroyPipeline(device, pipelines.skybox, nullptr); - vkDestroyPipeline(device, pipelines.reflect, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // This sample requires support for cube map arrays - if (deviceFeatures.imageCubeArray) { - enabledFeatures.imageCubeArray = VK_TRUE; - } else { - vks::tools::exitFatal("Selected GPU does not support cube map arrays!", VK_ERROR_FEATURE_NOT_PRESENT); - } - enabledFeatures.imageCubeArray = VK_TRUE; - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - }; - - // Loads a cubemap array from a file, uploads it to the device and create all Vulkan resources required to display it - void loadCubemapArray(std::string filename, VkFormat format) - { - ktxResult result; - ktxTexture* ktxTexture; - -#if defined(__ANDROID__) - // Textures are stored inside the apk on Android (compressed) - // So they need to be loaded via the asset manager - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); - if (!asset) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - size_t size = AAsset_getLength(asset); - assert(size > 0); - - ktx_uint8_t *textureData = new ktx_uint8_t[size]; - AAsset_read(asset, textureData, size); - AAsset_close(asset); - result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); - delete[] textureData; -#else - if (!vks::tools::fileExists(filename)) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); -#endif - assert(result == KTX_SUCCESS); - - // Get properties required for using and upload texture data from the ktx texture object - cubeMapArray.width = ktxTexture->baseWidth; - cubeMapArray.height = ktxTexture->baseHeight; - cubeMapArray.mipLevels = ktxTexture->numLevels; - cubeMapArray.layerCount = ktxTexture->numLayers; - ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); - ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture); - - vks::Buffer sourceData; - - // Create a host-visible source buffer that contains the raw image data - VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = ktxTextureSize; - bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &sourceData.buffer)); - - // Get memory requirements for the source buffer (alignment, memory type bits) - VkMemoryRequirements memReqs; - vkGetBufferMemoryRequirements(device, sourceData.buffer, &memReqs); - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - memAllocInfo.allocationSize = memReqs.size; - // Get memory type index for a host visible buffer - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &sourceData.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, sourceData.buffer, sourceData.memory, 0)); - - // Copy the ktx image data into the source buffer - uint8_t *data; - VK_CHECK_RESULT(vkMapMemory(device, sourceData.memory, 0, memReqs.size, 0, (void **)&data)); - memcpy(data, ktxTextureData, ktxTextureSize); - vkUnmapMemory(device, sourceData.memory); - - // Create optimal tiled target image - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.mipLevels = cubeMapArray.mipLevels; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.extent = { cubeMapArray.width, cubeMapArray.height, 1 }; - imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - // Cube faces count as array layers in Vulkan - imageCreateInfo.arrayLayers = 6 * cubeMapArray.layerCount; - // This flag is required for cube map images - imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &cubeMapArray.image)); - - // Allocate memory for the cube map array image - vkGetImageMemoryRequirements(device, cubeMapArray.image, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &cubeMapArray.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, cubeMapArray.image, cubeMapArray.deviceMemory, 0)); - - /* - We now copy the parts that make up the cube map array to our image via a command buffer - Cube map arrays in ktx are stored with a layout like this: - - Mip Level 0 - - Layer 0 (= Cube map 0) - - Face +X - - Face -X - - Face +Y - - Face -Y - - Face +Z - - Face -Z - - Layer 1 (= Cube map 1) - - Face +X - ... - - Mip Level 1 - - Layer 0 (= Cube map 0) - - Face +X - ... - - Layer 1 (= Cube map 1) - - Face +X - ... - */ - - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // Setup buffer copy regions for each face including all of its miplevels - std::vector bufferCopyRegions; - uint32_t offset = 0; - for (uint32_t face = 0; face < 6; face++) { - for (uint32_t layer = 0; layer < ktxTexture->numLayers; layer++) { - for (uint32_t level = 0; level < ktxTexture->numLevels; level++) { - ktx_size_t offset; - KTX_error_code ret = ktxTexture_GetImageOffset(ktxTexture, level, layer, face, &offset); - assert(ret == KTX_SUCCESS); - VkBufferImageCopy bufferCopyRegion = {}; - bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - bufferCopyRegion.imageSubresource.mipLevel = level; - bufferCopyRegion.imageSubresource.baseArrayLayer = layer * 6 + face; - bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> level; - bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> level; - bufferCopyRegion.imageExtent.depth = 1; - bufferCopyRegion.bufferOffset = offset; - bufferCopyRegions.push_back(bufferCopyRegion); - } - } - } - - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = cubeMapArray.mipLevels; - subresourceRange.layerCount = 6 * cubeMapArray.layerCount; - - // Transition target image to accept the writes from our buffer to image copies - vks::tools::setImageLayout(copyCmd, cubeMapArray.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceRange); - - // Copy the cube map array buffer parts from the staging buffer to the optimal tiled image - vkCmdCopyBufferToImage( - copyCmd, - sourceData.buffer, - cubeMapArray.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - static_cast(bufferCopyRegions.size()), - bufferCopyRegions.data() - ); - - // Transition image to shader read layout - cubeMapArray.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vks::tools::setImageLayout(copyCmd, cubeMapArray.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, cubeMapArray.imageLayout, subresourceRange); - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - // Create sampler - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = static_cast(cubeMapArray.mipLevels); - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - sampler.maxAnisotropy = 1.0f; - if (vulkanDevice->features.samplerAnisotropy) - { - sampler.maxAnisotropy = vulkanDevice->properties.limits.maxSamplerAnisotropy; - sampler.anisotropyEnable = VK_TRUE; - } - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &cubeMapArray.sampler)); - - // Create the image view for a cube map array - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; - view.format = format; - view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - view.subresourceRange.layerCount = 6 * cubeMapArray.layerCount; - view.subresourceRange.levelCount = cubeMapArray.mipLevels; - view.image = cubeMapArray.image; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &cubeMapArray.view)); - - // Clean up staging resources - vkFreeMemory(device, sourceData.memory, nullptr); - vkDestroyBuffer(device, sourceData.buffer, nullptr); - ktxTexture_Destroy(ktxTexture); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - // Skybox - if (displaySkybox) - { - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skybox); - models.skybox.draw(drawCmdBuffers[i]); - } - - // 3D object - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.reflect); - models.objects[models.objectIndex].draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY; - // Skybox - models.skybox.loadFromFile(getAssetPath() + "models/cube.gltf", vulkanDevice, queue, glTFLoadingFlags); - // Objects - std::vector filenames = { "sphere.gltf", "teapot.gltf", "torusknot.gltf", "venus.gltf" }; - objectNames = { "Sphere", "Teapot", "Torusknot", "Venus" }; - models.objects.resize(filenames.size()); - for (size_t i = 0; i < filenames.size(); i++) { - models.objects[i].loadFromFile(getAssetPath() + "models/" + filenames[i], vulkanDevice, queue, glTFLoadingFlags); - } - // Load the cube map array from a ktx texture file - loadCubemapArray(getAssetPath() + "textures/cubemap_array.ktx", VK_FORMAT_R8G8B8A8_UNORM); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - // Image descriptor for the cube map array texture - VkDescriptorImageInfo textureDescriptor = vks::initializers::descriptorImageInfo(cubeMapArray.sampler, cubeMapArray.view, cubeMapArray.imageLayout); - - std::vector writeDescriptorSets = - { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Fragment shader cubemap sampler - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textureDescriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - const VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal }); - - // Skybox pipeline (background cube) - shaderStages[0] = loadShader(getShadersPath() + "texturecubemaparray/skybox.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "texturecubemaparray/skybox.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.skybox)); - - // Cube map reflect pipeline - shaderStages[0] = loadShader(getShadersPath() + "texturecubemaparray/reflect.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "texturecubemaparray/reflect.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // Enable depth test and write - depthStencilState.depthWriteEnable = VK_TRUE; - depthStencilState.depthTestEnable = VK_TRUE; - // Flip cull mode - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.reflect)); - } - - void prepareUniformBuffers() - { - // Object vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); - // Map persistent - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.modelView = camera.matrices.view; - uniformData.inverseModelview = glm::inverse(camera.matrices.view); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - overlay->sliderInt("Cube map", &uniformData.cubeMapIndex, 0, cubeMapArray.layerCount - 1); - overlay->sliderFloat("LOD bias", &uniformData.lodBias, 0.0f, (float)cubeMapArray.mipLevels); - if (overlay->comboBox("Object type", &models.objectIndex, objectNames)) { - buildCommandBuffers(); - } - if (overlay->checkBox("Skybox", &displaySkybox)) { - buildCommandBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/texturemipmapgen/README.md b/examples/texturemipmapgen/README.md deleted file mode 100644 index da34b4ee..00000000 --- a/examples/texturemipmapgen/README.md +++ /dev/null @@ -1,201 +0,0 @@ -# Run-time mip-map generation - - - -## Synopsis - -Generates a complete texture mip-chain at runtime from a base image using image blits and proper image barriers. - -## Requirements -To downsample from one mip level to the next, we will be using [```vkCmdBlitImage```](https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkCmdBlitImage.html). This requires the format used to support the ```BLIT_SRC_BIT``` and the ```BLIT_DST_BIT``` flags. If these are not supported, the image format can't be used to blit and you'd either have to choose a different format or use e.g. a compute shader to generate mip levels. The example uses the ```VK_FORMAT_R8G8B8A8_UNORM``` that should support these flags on most implementations. - -***Note:*** Use [```vkGetPhysicalDeviceFormatProperties```](https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkGetPhysicalDeviceFormatProperties.html) to check if the format supports the blit flags first. - -## Description - -This examples demonstrates how to generate a complete texture mip-chain at runtime instead of loading offline generated mip-maps from a texture file. - -While usually not applied for textures stored on the disk (that usually have the mips generated offline and stored in the file, see [basic texture mapping example](../texture)) this technique is used textures are generated at runtime, e.g. when doing dynamic cubemaps or other render-to-texture effects. - -Having mip-maps for runtime generated textures offers lots of benefits, both in terms of image stability and performance. Without mip mapping the image will become noisy, especially with high frequency textures (and texture components like specular) and using mip mapping will result in higher performance due to caching. - -Though this example only generates one mip-chain for a single texture at the beginning this technique can also be used during normal frame rendering to generate mip-chains for dynamic textures. - -Some GPUs also offer ```asynchronous transfer queues``` (check for queue families with only the ? ```VK_QUEUE_TRANSFER_BIT``` set) that may be used to speed up such operations. - -## Points of interest - -### Image setup -Even though we'll only upload the first mip level initially, we create the image with number of desired mip levels. The following formula is used to calculate the number of mip levels based on the max. image extent: - -```cpp -texture.mipLevels = floor(log2(std::max(texture.width, texture.height))) + 1; -``` - -This is then passed to the image creat info: - -```cpp -VkImageCreateInfo imageCreateInfo = vkTools::initializers::imageCreateInfo(); -imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; -imageCreateInfo.format = format; -imageCreateInfo.mipLevels = texture.mipLevels; -... -``` - -Setting the number of desired mip levels is necessary as this is used for allocating the right amount of memory for the image (```vkAllocateMemory```). - -### Upload base mip level - -Before generating the mip-chain we need to copy the image data loaded from disk into the newly generated image. This image will be the base for our mip-chain: - -```cpp -VkBufferImageCopy bufferCopyRegion = {}; -bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; -bufferCopyRegion.imageSubresource.mipLevel = 0; -bufferCopyRegion.imageExtent.width = texture.width; -bufferCopyRegion.imageExtent.height = texture.height; -bufferCopyRegion.imageExtent.depth = 1; - -vkCmdCopyBufferToImage(copyCmd, stagingBuffer, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion); -``` - -### Prepare base mip level -As we are going to blit ***from*** the base mip-level just uploaded we also need to set insert an image memory barrier that sets the image layout to ```TRANSFER_SRC``` for the base mip level: - -```cpp -VkImageSubresourceRange subresourceRange = {}; -subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; -subresourceRange.levelCount = 1; -subresourceRange.layerCount = 1; - -vks::tools::insertImageMemoryBarrier( - copyCmd, - texture.image, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - subresourceRange); -``` - -### Generating the mip-chain -There are two different ways of generating the mip-chain. The first one is to blit down the whole mip-chain from level n-1 to n, the other way would be to always use the base image and blit down from that to all levels. This example uses the first one. - -***Note:*** Blitting (same for copying) images is done inside of a command buffer that has to be submitted and as such has to be synchronized before using the new image with e.g. a ```vkFence```. - -We simply loop over all remaining mip levels (level 0 was loaded from disk) and prepare a ```VkImageBlit``` structure for each blit from mip level i-1 to level i. - -First the source for out blit. This is the previous mip level. The dimensions of the blit source are specified by srcOffset: -```cpp -for (int32_t i = 1; i < texture.mipLevels; i++) -{ - VkImageBlit imageBlit{}; - - // Source - imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageBlit.srcSubresource.layerCount = 1; - imageBlit.srcSubresource.mipLevel = i-1; - imageBlit.srcOffsets[1].x = int32_t(texture.width >> (i - 1)); - imageBlit.srcOffsets[1].y = int32_t(texture.height >> (i - 1)); - imageBlit.srcOffsets[1].z = 1; -``` -Setup for the destination mip level (1), with the dimensions for the blit destination specified in dstOffsets[1]: -```cpp - // Destination - imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageBlit.dstSubresource.layerCount = 1; - imageBlit.dstSubresource.mipLevel = i; - imageBlit.dstOffsets[1].x = int32_t(texture.width >> i); - imageBlit.dstOffsets[1].y = int32_t(texture.height >> i); - imageBlit.dstOffsets[1].z = 1; -``` - -Before we can blit to this mip level, we need to transition its image layout to ```TRANSFER_DST```: -```cpp - VkImageSubresourceRange mipSubRange = {}; - mipSubRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - mipSubRange.baseMipLevel = i; - mipSubRange.levelCount = 1; - mipSubRange.layerCount = 1; - - // Prepare current mip level as image blit destination - vks::tools::insertImageMemoryBarrier( - blitCmd, - texture.image, - 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - mipSubRange); -``` -Note that we set the ```baseMipLevel``` member of the subresource range so the image memory barrier will only affect the one mip level we want to copy to. - -Now that the mip level we want to copy from and the one we'll copy to have are in the proper layout (transfer source and destination) we can issue the [```vkCmdBlitImage```](https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkCmdBlitImage.html) to copy from mip level (i-1) to mip level (i): - -```cpp - vkCmdBlitImage( - blitCmd, - texture.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - texture.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &imageBlit, - VK_FILTER_LINEAR); -``` -```vkCmdBlitImage``` does the (down) scaling from mip level (i-1) to mip level (i) using a linear filter. - -After the blit is done we can use this mip level as a base for the next level, so we transition the layout from ```TRANSFER_DST_OPTIMAL``` to ```TRANSFER_SRC_OPTIMAL``` so we can use this level as transfer source for the next level: - -```cpp - // Prepare current mip level as image blit source for next level - vks::tools::insertImageMemoryBarrier( - copyCmd, - texture.image, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - mipSubRange); -} -``` - -### Final image layout transitions -Once the loop is done we need to transition all mip levels of the image to their actual usage layout, which is ```SHADER_READ``` for this example. Note that after the loop all levels will be in the ```TRANSER_SRC``` layout allowing us to transfer the whole image at once: - -```cpp - subresourceRange.levelCount = texture.mipLevels; - vks::tools::insertImageMemoryBarrier( - copyCmd, - texture.image, - VK_ACCESS_TRANSFER_READ_BIT, - VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - subresourceRange); -``` - -Submitting that command buffer will result in an image with a complete mip-chain and all mip levels being transitioned to the proper image layout for shader reads. - -### Image View creation -The Image View also requires information about how many Mip Levels are used. This is specified in the ```VkImageViewCreateInfo.subresourceRange.levelCount``` field. - -```cpp - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.image = texture.image; - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.format = format; - view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view.subresourceRange.baseMipLevel = 0; - view.subresourceRange.baseArrayLayer = 0; - view.subresourceRange.layerCount = 1; - view.subresourceRange.levelCount = texture.mipLevels; -``` diff --git a/examples/texturemipmapgen/texturemipmapgen.cpp b/examples/texturemipmapgen/texturemipmapgen.cpp deleted file mode 100644 index 734d3a8e..00000000 --- a/examples/texturemipmapgen/texturemipmapgen.cpp +++ /dev/null @@ -1,555 +0,0 @@ -/* -* Vulkan Example - Runtime mip map generation -* -* This samples shows how to generate a full mip-chain from a top-level image and how different sampling modes compare -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" -#include -#include - -class VulkanExample : public VulkanExampleBase -{ -public: - struct Texture { - VkImage image{ VK_NULL_HANDLE }; - VkDeviceMemory deviceMemory{ VK_NULL_HANDLE }; - VkImageView view{ VK_NULL_HANDLE }; - uint32_t width{ 0 }; - uint32_t height{ 0 }; - uint32_t mipLevels{ 0 }; - } texture; - - // To demonstrate mip mapping and filtering this example uses separate samplers - std::vector samplerNames{ "No mip maps" , "Mip maps (bilinear)" , "Mip maps (anisotropic)" }; - std::vector samplers{}; - - vkglTF::Model model; - - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - glm::vec4 viewPos; - float lodBias = 0.0f; - int32_t samplerIndex = 2; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - VulkanExample() : VulkanExampleBase() - { - title = "Runtime mip map generation"; - camera.type = Camera::CameraType::firstperson; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 1024.0f); - camera.setRotation(glm::vec3(0.0f, 90.0f, 0.0f)); - camera.setTranslation(glm::vec3(40.75f, 0.0f, 0.0f)); - camera.movementSpeed = 2.5f; - camera.rotationSpeed = 0.5f; - timerSpeed *= 0.05f; - } - - ~VulkanExample() - { - if (device) { - destroyTextureImage(texture); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); - for (auto sampler : samplers) { - vkDestroySampler(device, sampler, nullptr); - } - } - } - - virtual void getEnabledFeatures() - { - if (deviceFeatures.samplerAnisotropy) { - enabledFeatures.samplerAnisotropy = VK_TRUE; - } - } - - // Loads a full sized image from disk, generates a Vulkan image (texture) from it and creates a full mip chain using blits - void loadTextureAndGenerateMips(std::string filename, VkFormat format) - { - ktxResult result; - ktxTexture* ktxTexture; - -#if defined(__ANDROID__) - // Textures are stored inside the apk on Android (compressed) - // So they need to be loaded via the asset manager - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); - if (!asset) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - size_t size = AAsset_getLength(asset); - assert(size > 0); - - ktx_uint8_t *textureData = new ktx_uint8_t[size]; - AAsset_read(asset, textureData, size); - AAsset_close(asset); - result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); - delete[] textureData; -#else - if (!vks::tools::fileExists(filename)) { - vks::tools::exitFatal("Could not load texture from " + filename + "\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - } - result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); -#endif - assert(result == KTX_SUCCESS); - - texture.width = ktxTexture->baseWidth; - texture.height = ktxTexture->baseHeight; - ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); - ktx_size_t ktxTextureSize = ktxTexture_GetImageSize(ktxTexture, 0); - - // calculate num of mip maps - // numLevels = 1 + floor(log2(max(w, h, d))) - // Calculated as log2(max(width, height, depth))c + 1 (see specs) - texture.mipLevels = static_cast(floor(log2(std::max(texture.width, texture.height))) + 1); - - // Get device properties for the requested texture format - VkFormatProperties formatProperties; - vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties); - // Mip-chain generation requires support for blit source and destination - assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT); - assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT); - - VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs = {}; - - // Create a host-visible staging buffer that contains the raw image data - VkBuffer stagingBuffer; - VkDeviceMemory stagingMemory; - - VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = ktxTextureSize; - // This buffer is used as a transfer source for the buffer copy - bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer)); - vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0)); - - // Copy texture data into staging buffer - uint8_t *data; - VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data)); - memcpy(data, ktxTextureData, ktxTextureSize); - vkUnmapMemory(device, stagingMemory); - - // Create optimal tiled target image - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.mipLevels = texture.mipLevels; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.extent = { texture.width, texture.height, 1 }; - imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &texture.image)); - vkGetImageMemoryRequirements(device, texture.image, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &texture.deviceMemory)); - VK_CHECK_RESULT(vkBindImageMemory(device, texture.image, texture.deviceMemory, 0)); - - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.levelCount = 1; - subresourceRange.layerCount = 1; - - // Optimal image will be used as destination for the copy, so we must transfer from our initial undefined image layout to the transfer destination layout - vks::tools::insertImageMemoryBarrier( - copyCmd, - texture.image, - 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - subresourceRange); - - // Copy the first mip of the chain, remaining mips will be generated - VkBufferImageCopy bufferCopyRegion = {}; - bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - bufferCopyRegion.imageSubresource.mipLevel = 0; - bufferCopyRegion.imageSubresource.baseArrayLayer = 0; - bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = texture.width; - bufferCopyRegion.imageExtent.height = texture.height; - bufferCopyRegion.imageExtent.depth = 1; - - vkCmdCopyBufferToImage(copyCmd, stagingBuffer, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion); - - // Transition first mip level to transfer source for read during blit - vks::tools::insertImageMemoryBarrier( - copyCmd, - texture.image, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - subresourceRange); - - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - // Clean up staging resources - vkFreeMemory(device, stagingMemory, nullptr); - vkDestroyBuffer(device, stagingBuffer, nullptr); - ktxTexture_Destroy(ktxTexture); - - // Generate the mip chain - // --------------------------------------------------------------- - // We copy down the whole mip chain doing a blit from mip-1 to mip - // An alternative way would be to always blit from the first mip level and sample that one down - VkCommandBuffer blitCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - // Copy down mips from n-1 to n - for (uint32_t i = 1; i < texture.mipLevels; i++) - { - VkImageBlit imageBlit{}; - - // Source - imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageBlit.srcSubresource.layerCount = 1; - imageBlit.srcSubresource.mipLevel = i-1; - imageBlit.srcOffsets[1].x = int32_t(texture.width >> (i - 1)); - imageBlit.srcOffsets[1].y = int32_t(texture.height >> (i - 1)); - imageBlit.srcOffsets[1].z = 1; - - // Destination - imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageBlit.dstSubresource.layerCount = 1; - imageBlit.dstSubresource.mipLevel = i; - imageBlit.dstOffsets[1].x = int32_t(texture.width >> i); - imageBlit.dstOffsets[1].y = int32_t(texture.height >> i); - imageBlit.dstOffsets[1].z = 1; - - VkImageSubresourceRange mipSubRange = {}; - mipSubRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - mipSubRange.baseMipLevel = i; - mipSubRange.levelCount = 1; - mipSubRange.layerCount = 1; - - // Prepare current mip level as image blit destination - vks::tools::insertImageMemoryBarrier( - blitCmd, - texture.image, - 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - mipSubRange); - - // Blit from previous level - vkCmdBlitImage( - blitCmd, - texture.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - texture.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &imageBlit, - VK_FILTER_LINEAR); - - // Prepare current mip level as image blit source for next level - vks::tools::insertImageMemoryBarrier( - blitCmd, - texture.image, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - mipSubRange); - } - - // After the loop, all mip layers are in TRANSFER_SRC layout, so transition all to SHADER_READ - subresourceRange.levelCount = texture.mipLevels; - vks::tools::insertImageMemoryBarrier( - blitCmd, - texture.image, - VK_ACCESS_TRANSFER_READ_BIT, - VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - subresourceRange); - - vulkanDevice->flushCommandBuffer(blitCmd, queue, true); - // --------------------------------------------------------------- - - // Create some samplers with different settings that can be selected via the UI - samplers.resize(3); - - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; - sampler.addressModeV = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; - sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; - sampler.mipLodBias = 0.0f; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = 0.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - sampler.maxAnisotropy = 1.0; - sampler.anisotropyEnable = VK_FALSE; - - // Without mip mapping - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &samplers[0])); - - // With mip mapping - sampler.maxLod = (float)texture.mipLevels; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &samplers[1])); - - // With mip mapping and anisotropic filtering - if (vulkanDevice->features.samplerAnisotropy) - { - sampler.maxAnisotropy = vulkanDevice->properties.limits.maxSamplerAnisotropy; - sampler.anisotropyEnable = VK_TRUE; - } - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &samplers[2])); - - // Create image view - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.image = texture.image; - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.format = format; - view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view.subresourceRange.baseMipLevel = 0; - view.subresourceRange.baseArrayLayer = 0; - view.subresourceRange.layerCount = 1; - view.subresourceRange.levelCount = texture.mipLevels; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &texture.view)); - } - - // Free all Vulkan resources used a texture object - void destroyTextureImage(Texture texture) - { - vkDestroyImageView(device, texture.view, nullptr); - vkDestroyImage(device, texture.image, nullptr); - vkFreeMemory(device, texture.deviceMemory, nullptr); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - model.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - model.loadFromFile(getAssetPath() + "models/tunnel_cylinder.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::FlipY); - loadTextureAndGenerateMips(getAssetPath() + "textures/metalplate_nomips_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_SAMPLER, 3), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // Binding 1: Sampled image - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - // Binding 2: Array with 3 samplers - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2, 3), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - VkDescriptorImageInfo textureDescriptor = vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, texture.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - std::vector writeDescriptorSets = { - // Binding 0: Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1: Sampled image - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, &textureDescriptor) - }; - - // Binding 2: Contains an array of samplers that can be switched from the UI to demonstrate different filteirng modes - std::vector samplerDescriptors; - for (auto i = 0; i < samplers.size(); i++) { - samplerDescriptors.push_back(vks::initializers::descriptorImageInfo(samplers[i], VK_NULL_HANDLE, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - } - VkWriteDescriptorSet samplerDescriptorWrite{}; - samplerDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - samplerDescriptorWrite.dstSet = descriptorSet; - samplerDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - samplerDescriptorWrite.descriptorCount = static_cast(samplerDescriptors.size()); - samplerDescriptorWrite.pImageInfo = samplerDescriptors.data(); - samplerDescriptorWrite.dstBinding = 2; - samplerDescriptorWrite.dstArrayElement = 0; - writeDescriptorSets.push_back(samplerDescriptorWrite); - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - shaderStages[0] = loadShader(getShadersPath() + "texturemipmapgen/texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "texturemipmapgen/texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Normal }); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData), &uniformData)); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.model = glm::rotate(glm::mat4(1.0f), glm::radians(timer * 360.0f), glm::vec3(1.0f, 0.0f, 0.0f)); - uniformData.viewPos = glm::vec4(camera.position, 0.0f) * glm::vec4(-1.0f); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->sliderFloat("LOD bias", &uniformData.lodBias, 0.0f, (float)texture.mipLevels)) { - updateUniformBuffers(); - } - if (overlay->comboBox("Sampler type", &uniformData.samplerIndex, samplerNames)) { - updateUniformBuffers(); - } - } - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/texturesparseresidency/texturesparseresidency.cpp b/examples/texturesparseresidency/texturesparseresidency.cpp deleted file mode 100644 index fad0d98a..00000000 --- a/examples/texturesparseresidency/texturesparseresidency.cpp +++ /dev/null @@ -1,871 +0,0 @@ -/* -* Vulkan Example - Sparse texture residency example -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -/* -* Important note : This sample is work-in-progress and works basically, but it's not finished -*/ - -#include "texturesparseresidency.h" - -/* - Virtual texture page - Contains all functions and objects for a single page of a virtual texture - */ - -VirtualTexturePage::VirtualTexturePage() -{ - // Pages are initially not backed up by memory (non-resident) - imageMemoryBind.memory = VK_NULL_HANDLE; -} - -bool VirtualTexturePage::resident() -{ - return (imageMemoryBind.memory != VK_NULL_HANDLE); -} - -// Allocate Vulkan memory for the virtual page -bool VirtualTexturePage::allocate(VkDevice device, uint32_t memoryTypeIndex) -{ - if (imageMemoryBind.memory != VK_NULL_HANDLE) - { - return false; - }; - - imageMemoryBind = {}; - - VkMemoryAllocateInfo allocInfo = vks::initializers::memoryAllocateInfo(); - allocInfo.allocationSize = size; - allocInfo.memoryTypeIndex = memoryTypeIndex; - VK_CHECK_RESULT(vkAllocateMemory(device, &allocInfo, nullptr, &imageMemoryBind.memory)); - - VkImageSubresource subResource{}; - subResource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subResource.mipLevel = mipLevel; - subResource.arrayLayer = layer; - - // Sparse image memory binding - imageMemoryBind.subresource = subResource; - imageMemoryBind.extent = extent; - imageMemoryBind.offset = offset; - return true; -} - -// Release Vulkan memory allocated for this page -bool VirtualTexturePage::release(VkDevice device) -{ - del= false; - if (imageMemoryBind.memory != VK_NULL_HANDLE) - { - vkFreeMemory(device, imageMemoryBind.memory, nullptr); - imageMemoryBind.memory = VK_NULL_HANDLE; - return true; - } - return false; -} - -/* - Virtual texture - Contains the virtual pages and memory binding information for a whole virtual texture - */ - -VirtualTexturePage* VirtualTexture::addPage(VkOffset3D offset, VkExtent3D extent, const VkDeviceSize size, const uint32_t mipLevel, uint32_t layer) -{ - VirtualTexturePage newPage{}; - newPage.offset = offset; - newPage.extent = extent; - newPage.size = size; - newPage.mipLevel = mipLevel; - newPage.layer = layer; - newPage.index = static_cast(pages.size()); - newPage.imageMemoryBind = {}; - newPage.imageMemoryBind.offset = offset; - newPage.imageMemoryBind.extent = extent; - newPage.del = false; - pages.push_back(newPage); - return &pages.back(); -} - -// Call before sparse binding to update memory bind list etc. -void VirtualTexture::updateSparseBindInfo(std::vector &bindingChangedPages, bool del) -{ - // Update list of memory-backed sparse image memory binds - //sparseImageMemoryBinds.resize(pages.size()); - sparseImageMemoryBinds.clear(); - for (auto page : bindingChangedPages) - { - sparseImageMemoryBinds.push_back(page.imageMemoryBind); - if (del) - { - sparseImageMemoryBinds[sparseImageMemoryBinds.size() - 1].memory = VK_NULL_HANDLE; - } - } - // Update sparse bind info - bindSparseInfo = vks::initializers::bindSparseInfo(); - // todo: Semaphore for queue submission - // bindSparseInfo.signalSemaphoreCount = 1; - // bindSparseInfo.pSignalSemaphores = &bindSparseSemaphore; - - // Image memory binds - imageMemoryBindInfo = {}; - imageMemoryBindInfo.image = image; - imageMemoryBindInfo.bindCount = static_cast(sparseImageMemoryBinds.size()); - imageMemoryBindInfo.pBinds = sparseImageMemoryBinds.data(); - bindSparseInfo.imageBindCount = (imageMemoryBindInfo.bindCount > 0) ? 1 : 0; - bindSparseInfo.pImageBinds = &imageMemoryBindInfo; - - // Opaque image memory binds for the mip tail - opaqueMemoryBindInfo.image = image; - opaqueMemoryBindInfo.bindCount = static_cast(opaqueMemoryBinds.size()); - opaqueMemoryBindInfo.pBinds = opaqueMemoryBinds.data(); - bindSparseInfo.imageOpaqueBindCount = (opaqueMemoryBindInfo.bindCount > 0) ? 1 : 0; - bindSparseInfo.pImageOpaqueBinds = &opaqueMemoryBindInfo; -} - -// Release all Vulkan resources -void VirtualTexture::destroy() -{ - for (auto page : pages) - { - page.release(device); - } - for (auto bind : opaqueMemoryBinds) - { - vkFreeMemory(device, bind.memory, nullptr); - } - // Clean up mip tail - if (mipTailimageMemoryBind.memory != VK_NULL_HANDLE) { - vkFreeMemory(device, mipTailimageMemoryBind.memory, nullptr); - } -} - -/* - Vulkan Example class -*/ -VulkanExample::VulkanExample() : VulkanExampleBase() -{ - title = "Sparse texture residency"; - std::cout.imbue(std::locale("")); - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -12.0f)); - camera.setRotation(glm::vec3(-90.0f, 0.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); -} - -VulkanExample::~VulkanExample() -{ - // Clean up used Vulkan resources - // Note : Inherited destructor cleans up resources stored in base class - destroyTextureImage(texture); - vkDestroySemaphore(device, bindSparseSemaphore, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBuffer.destroy(); -} - -void VulkanExample::getEnabledFeatures() -{ - if (deviceFeatures.sparseBinding && deviceFeatures.sparseResidencyImage2D) { - enabledFeatures.shaderResourceResidency = VK_TRUE; - enabledFeatures.sparseBinding = VK_TRUE; - enabledFeatures.sparseResidencyImage2D = VK_TRUE; - } - else { - std::cout << "Sparse binding not supported" << std::endl; - } -} - -glm::uvec3 VulkanExample::alignedDivision(const VkExtent3D& extent, const VkExtent3D& granularity) -{ - glm::uvec3 res; - res.x = extent.width / granularity.width + ((extent.width % granularity.width) ? 1u : 0u); - res.y = extent.height / granularity.height + ((extent.height % granularity.height) ? 1u : 0u); - res.z = extent.depth / granularity.depth + ((extent.depth % granularity.depth) ? 1u : 0u); - return res; -} - -void VulkanExample::prepareSparseTexture(uint32_t width, uint32_t height, uint32_t layerCount, VkFormat format) -{ - texture.device = vulkanDevice->logicalDevice; - texture.width = width; - texture.height = height; - texture.mipLevels = static_cast(floor(log2(std::max(width, height))) + 1); - texture.layerCount = layerCount; - texture.format = format; - - texture.subRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, texture.mipLevels, 0, 1 }; - // Get device properties for the requested texture format - VkFormatProperties formatProperties; - vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties); - - const VkImageType imageType = VK_IMAGE_TYPE_2D; - const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; - const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - const VkImageTiling imageTiling = VK_IMAGE_TILING_OPTIMAL; - - // Get sparse image properties - std::vector sparseProperties; - // Sparse properties count for the desired format - uint32_t sparsePropertiesCount; - vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, imageType, sampleCount, imageUsage, imageTiling, &sparsePropertiesCount, nullptr); - // Check if sparse is supported for this format - if (sparsePropertiesCount == 0) - { - std::cout << "Error: Requested format does not support sparse features!" << std::endl; - return; - } - - // Get actual image format properties - sparseProperties.resize(sparsePropertiesCount); - vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, imageType, sampleCount, imageUsage, imageTiling, &sparsePropertiesCount, sparseProperties.data()); - - std::cout << "Sparse image format properties: " << sparsePropertiesCount << std::endl; - for (auto props : sparseProperties) - { - std::cout << "\t Image granularity: w = " << props.imageGranularity.width << " h = " << props.imageGranularity.height << " d = " << props.imageGranularity.depth << std::endl; - std::cout << "\t Aspect mask: " << props.aspectMask << std::endl; - std::cout << "\t Flags: " << props.flags << std::endl; - } - - // Create sparse image - VkImageCreateInfo sparseImageCreateInfo = vks::initializers::imageCreateInfo(); - sparseImageCreateInfo.imageType = imageType; - sparseImageCreateInfo.format = texture.format; - sparseImageCreateInfo.mipLevels = texture.mipLevels; - sparseImageCreateInfo.arrayLayers = texture.layerCount; - sparseImageCreateInfo.samples = sampleCount; - sparseImageCreateInfo.tiling = imageTiling; - sparseImageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - sparseImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - sparseImageCreateInfo.extent = { texture.width, texture.height, 1 }; - sparseImageCreateInfo.usage = imageUsage; - sparseImageCreateInfo.flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &sparseImageCreateInfo, nullptr, &texture.image)); - - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout(copyCmd, texture.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, texture.subRange); - vulkanDevice->flushCommandBuffer(copyCmd, queue); - - // Get memory requirements - VkMemoryRequirements sparseImageMemoryReqs; - // Sparse image memory requirement counts - vkGetImageMemoryRequirements(device, texture.image, &sparseImageMemoryReqs); - - std::cout << "Image memory requirements:" << std::endl; - std::cout << "\t Size: " << sparseImageMemoryReqs.size << std::endl; - std::cout << "\t Alignment: " << sparseImageMemoryReqs.alignment << std::endl; - - // Check requested image size against hardware sparse limit - if (sparseImageMemoryReqs.size > vulkanDevice->properties.limits.sparseAddressSpaceSize) - { - std::cout << "Error: Requested sparse image size exceeds supports sparse address space size!" << std::endl; - return; - }; - - // Get sparse memory requirements - // Count - uint32_t sparseMemoryReqsCount = 32; - std::vector sparseMemoryReqs(sparseMemoryReqsCount); - vkGetImageSparseMemoryRequirements(device, texture.image, &sparseMemoryReqsCount, sparseMemoryReqs.data()); - if (sparseMemoryReqsCount == 0) - { - std::cout << "Error: No memory requirements for the sparse image!" << std::endl; - return; - } - sparseMemoryReqs.resize(sparseMemoryReqsCount); - // Get actual requirements - vkGetImageSparseMemoryRequirements(device, texture.image, &sparseMemoryReqsCount, sparseMemoryReqs.data()); - - std::cout << "Sparse image memory requirements: " << sparseMemoryReqsCount << std::endl; - for (auto reqs : sparseMemoryReqs) - { - std::cout << "\t Image granularity: w = " << reqs.formatProperties.imageGranularity.width << " h = " << reqs.formatProperties.imageGranularity.height << " d = " << reqs.formatProperties.imageGranularity.depth << std::endl; - std::cout << "\t Mip tail first LOD: " << reqs.imageMipTailFirstLod << std::endl; - std::cout << "\t Mip tail size: " << reqs.imageMipTailSize << std::endl; - std::cout << "\t Mip tail offset: " << reqs.imageMipTailOffset << std::endl; - std::cout << "\t Mip tail stride: " << reqs.imageMipTailStride << std::endl; - //todo:multiple reqs - texture.mipTailStart = reqs.imageMipTailFirstLod; - } - - // Get sparse image requirements for the color aspect - VkSparseImageMemoryRequirements sparseMemoryReq; - bool colorAspectFound = false; - for (auto reqs : sparseMemoryReqs) - { - if (reqs.formatProperties.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) - { - sparseMemoryReq = reqs; - colorAspectFound = true; - break; - } - } - if (!colorAspectFound) - { - std::cout << "Error: Could not find sparse image memory requirements for color aspect bit!" << std::endl; - return; - } - - // @todo: proper comment - // Calculate number of required sparse memory bindings by alignment - assert((sparseImageMemoryReqs.size % sparseImageMemoryReqs.alignment) == 0); - texture.memoryTypeIndex = vulkanDevice->getMemoryType(sparseImageMemoryReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - texture.sparseImageMemoryRequirements = sparseMemoryReq; - - // The mip tail contains all mip levels > sparseMemoryReq.imageMipTailFirstLod - // Check if the format has a single mip tail for all layers or one mip tail for each layer - // @todo: Comment - texture.mipTailInfo.singleMipTail = sparseMemoryReq.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT; - texture.mipTailInfo.alingedMipSize = sparseMemoryReq.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT; - - // Sparse bindings for each mip level of all layers outside of the mip tail - for (uint32_t layer = 0; layer < texture.layerCount; layer++) - { - // sparseMemoryReq.imageMipTailFirstLod is the first mip level that's stored inside the mip tail - for (uint32_t mipLevel = 0; mipLevel < sparseMemoryReq.imageMipTailFirstLod; mipLevel++) - { - VkExtent3D extent; - extent.width = std::max(sparseImageCreateInfo.extent.width >> mipLevel, 1u); - extent.height = std::max(sparseImageCreateInfo.extent.height >> mipLevel, 1u); - extent.depth = std::max(sparseImageCreateInfo.extent.depth >> mipLevel, 1u); - - VkImageSubresource subResource{}; - subResource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subResource.mipLevel = mipLevel; - subResource.arrayLayer = layer; - - // Aligned sizes by image granularity - VkExtent3D imageGranularity = sparseMemoryReq.formatProperties.imageGranularity; - glm::uvec3 sparseBindCounts = alignedDivision(extent, imageGranularity); - glm::uvec3 lastBlockExtent; - lastBlockExtent.x = (extent.width % imageGranularity.width) ? extent.width % imageGranularity.width : imageGranularity.width; - lastBlockExtent.y = (extent.height % imageGranularity.height) ? extent.height % imageGranularity.height : imageGranularity.height; - lastBlockExtent.z = (extent.depth % imageGranularity.depth) ? extent.depth % imageGranularity.depth : imageGranularity.depth; - - // @todo: Comment - uint32_t index = 0; - for (uint32_t z = 0; z < sparseBindCounts.z; z++) - { - for (uint32_t y = 0; y < sparseBindCounts.y; y++) - { - for (uint32_t x = 0; x < sparseBindCounts.x; x++) - { - // Offset - VkOffset3D offset; - offset.x = x * imageGranularity.width; - offset.y = y * imageGranularity.height; - offset.z = z * imageGranularity.depth; - // Size of the page - VkExtent3D extent; - extent.width = (x == sparseBindCounts.x - 1) ? lastBlockExtent.x : imageGranularity.width; - extent.height = (y == sparseBindCounts.y - 1) ? lastBlockExtent.y : imageGranularity.height; - extent.depth = (z == sparseBindCounts.z - 1) ? lastBlockExtent.z : imageGranularity.depth; - - // Add new virtual page - VirtualTexturePage* newPage = texture.addPage(offset, extent, sparseImageMemoryReqs.alignment, mipLevel, layer); - newPage->imageMemoryBind.subresource = subResource; - - index++; - } - } - } - } - - // @todo: proper comment - // @todo: store in mip tail and properly release - // @todo: Only one block for single mip tail - if ((!texture.mipTailInfo.singleMipTail) && (sparseMemoryReq.imageMipTailFirstLod < texture.mipLevels)) - { - // Allocate memory for the mip tail - VkMemoryAllocateInfo allocInfo = vks::initializers::memoryAllocateInfo(); - allocInfo.allocationSize = sparseMemoryReq.imageMipTailSize; - allocInfo.memoryTypeIndex = texture.memoryTypeIndex; - - VkDeviceMemory deviceMemory; - VK_CHECK_RESULT(vkAllocateMemory(device, &allocInfo, nullptr, &deviceMemory)); - - // (Opaque) sparse memory binding - VkSparseMemoryBind sparseMemoryBind{}; - sparseMemoryBind.resourceOffset = sparseMemoryReq.imageMipTailOffset + layer * sparseMemoryReq.imageMipTailStride; - sparseMemoryBind.size = sparseMemoryReq.imageMipTailSize; - sparseMemoryBind.memory = deviceMemory; - - texture.opaqueMemoryBinds.push_back(sparseMemoryBind); - } - } // end layers and mips - - std::cout << "Texture info:" << std::endl; - std::cout << "\tDim: " << texture.width << " x " << texture.height << std::endl; - std::cout << "\tVirtual pages: " << texture.pages.size() << std::endl; - - // Check if format has one mip tail for all layers - if ((sparseMemoryReq.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT) && (sparseMemoryReq.imageMipTailFirstLod < texture.mipLevels)) - { - // Allocate memory for the mip tail - VkMemoryAllocateInfo allocInfo = vks::initializers::memoryAllocateInfo(); - allocInfo.allocationSize = sparseMemoryReq.imageMipTailSize; - allocInfo.memoryTypeIndex = texture.memoryTypeIndex; - - VkDeviceMemory deviceMemory; - VK_CHECK_RESULT(vkAllocateMemory(device, &allocInfo, nullptr, &deviceMemory)); - - // (Opaque) sparse memory binding - VkSparseMemoryBind sparseMemoryBind{}; - sparseMemoryBind.resourceOffset = sparseMemoryReq.imageMipTailOffset; - sparseMemoryBind.size = sparseMemoryReq.imageMipTailSize; - sparseMemoryBind.memory = deviceMemory; - - texture.opaqueMemoryBinds.push_back(sparseMemoryBind); - } - - // Create signal semaphore for sparse binding - VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &bindSparseSemaphore)); - - // Prepare bind sparse info for reuse in queue submission - texture.updateSparseBindInfo(texture.pages); - - // Bind to queue - // todo: in draw? - vkQueueBindSparse(queue, 1, &texture.bindSparseInfo, VK_NULL_HANDLE); - //todo: use sparse bind semaphore - vkQueueWaitIdle(queue); - - // Create sampler - VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = VK_FILTER_LINEAR; - sampler.minFilter = VK_FILTER_LINEAR; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.mipLodBias = 0.0f; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = static_cast(texture.mipLevels); - sampler.maxAnisotropy = vulkanDevice->features.samplerAnisotropy ? vulkanDevice->properties.limits.maxSamplerAnisotropy : 1.0f; - sampler.anisotropyEnable = false; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &texture.sampler)); - - // Create image view - VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); - view.image = VK_NULL_HANDLE; - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.format = format; - view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view.subresourceRange.baseMipLevel = 0; - view.subresourceRange.baseArrayLayer = 0; - view.subresourceRange.layerCount = 1; - view.subresourceRange.levelCount = texture.mipLevels; - view.image = texture.image; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &texture.view)); - - // Fill image descriptor image info that can be used during the descriptor set setup - texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - texture.descriptor.imageView = texture.view; - texture.descriptor.sampler = texture.sampler; -} - -// Free all Vulkan resources used a texture object -void VulkanExample::destroyTextureImage(SparseTexture texture) -{ - vkDestroyImageView(device, texture.view, nullptr); - vkDestroyImage(device, texture.image, nullptr); - vkDestroySampler(device, texture.sampler, nullptr); - texture.destroy(); -} - -void VulkanExample::buildCommandBuffers() -{ - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - plane.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } -} - -void VulkanExample::loadAssets() -{ - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - plane.loadFromFile(getAssetPath() + "models/plane.gltf", vulkanDevice, queue, glTFLoadingFlags); -} - -void VulkanExample::setupDescriptors() -{ - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - VK_SHADER_STAGE_VERTEX_BIT, - 0), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - VK_SHADER_STAGE_FRAGMENT_BIT, - 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Sets - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Fragment shader texture sampler - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &texture.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); -} - -void VulkanExample::preparePipelines() -{ - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo( pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV }); - - shaderStages[0] = loadShader(getShadersPath() + "texturesparseresidency/sparseresidency.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "texturesparseresidency/sparseresidency.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); -} - -// Prepare and initialize uniform buffer containing shader uniforms -void VulkanExample::prepareUniformBuffers() -{ - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData), &uniformData)); - updateUniformBuffers(); -} - -void VulkanExample::updateUniformBuffers() -{ - uniformData.projection = camera.matrices.perspective; - uniformData.model = camera.matrices.view; - uniformData.viewPos = camera.viewPos; - - VK_CHECK_RESULT(uniformBuffer.map()); - memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); - uniformBuffer.unmap(); -} - -void VulkanExample::prepare() -{ - VulkanExampleBase::prepare(); - // Check if the GPU supports sparse residency for 2D images - if (!vulkanDevice->features.sparseResidencyImage2D) { - vks::tools::exitFatal("Device does not support sparse residency for 2D images!", VK_ERROR_FEATURE_NOT_PRESENT); - } - loadAssets(); - prepareUniformBuffers(); - // Create a virtual texture with max. possible dimension (does not take up any VRAM yet) - prepareSparseTexture(4096, 4096, 1, VK_FORMAT_R8G8B8A8_UNORM); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; -} - -void VulkanExample::draw() -{ - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); -} - -void VulkanExample::render() -{ - if (!prepared) - return; - updateUniformBuffers(); - draw(); -} - -// Fills a buffer with random colors -void VulkanExample::randomPattern(uint8_t* buffer, uint32_t width, uint32_t height) -{ - std::random_device rd; - std::mt19937 rndEngine(rd()); - std::uniform_int_distribution rndDist(0, 255); - uint8_t rndVal[4] = { 0, 0, 0, 0 }; - while (rndVal[0] + rndVal[1] + rndVal[2] < 10) { - rndVal[0] = (uint8_t)rndDist(rndEngine); - rndVal[1] = (uint8_t)rndDist(rndEngine); - rndVal[2] = (uint8_t)rndDist(rndEngine); - } - rndVal[3] = 255; - for (uint32_t y = 0; y < height; y++) { - for (uint32_t x = 0; x < width; x++) { - for (uint32_t c = 0; c < 4; c++, ++buffer) { - *buffer = rndVal[c]; - } - } - } -} - -void VulkanExample::uploadContent(VirtualTexturePage page, VkImage image) -{ - // Generate some random image data and upload as a buffer - const size_t bufferSize = 4 * page.extent.width * page.extent.height; - - vks::Buffer imageBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &imageBuffer, - bufferSize)); - imageBuffer.map(); - - uint8_t* data = (uint8_t*)imageBuffer.mapped; - randomPattern(data, page.extent.height, page.extent.width); - - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout(copyCmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture.subRange, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - VkBufferImageCopy region{}; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageSubresource.mipLevel = page.mipLevel; - region.imageOffset = page.offset; - region.imageExtent = page.extent; - vkCmdCopyBufferToImage(copyCmd, imageBuffer.buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - vks::tools::setImageLayout(copyCmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, texture.subRange, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - vulkanDevice->flushCommandBuffer(copyCmd, queue); - - imageBuffer.destroy(); -} - -void VulkanExample::fillRandomPages() -{ - vkDeviceWaitIdle(device); - - std::default_random_engine rndEngine(benchmark.active ? 0 : std::random_device{}()); - std::uniform_real_distribution rndDist(0.0f, 1.0f); - - std::vector updatedPages; - std::vector bindingChangedPages; - for (auto& page : texture.pages) { - if (rndDist(rndEngine) < 0.5f) { - continue; - } - if (page.allocate(device, texture.memoryTypeIndex)) - { - bindingChangedPages.push_back(page); - } - updatedPages.push_back(page); - } - - // Update sparse queue binding - texture.updateSparseBindInfo(bindingChangedPages); - VkFenceCreateInfo fenceInfo = vks::initializers::fenceCreateInfo(VK_FLAGS_NONE); - VkFence fence; - VK_CHECK_RESULT(vkCreateFence(device, &fenceInfo, nullptr, &fence)); - vkQueueBindSparse(queue, 1, &texture.bindSparseInfo, fence); - vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX); - vkDestroyFence(device, fence, nullptr); - - for (auto &page: updatedPages) { - uploadContent(page, texture.image); - } -} - -void VulkanExample::fillMipTail() -{ - // Clean up previous mip tail memory allocation - if (texture.mipTailimageMemoryBind.memory != VK_NULL_HANDLE) { - vkFreeMemory(device, texture.mipTailimageMemoryBind.memory, nullptr); - } - - //@todo: WIP - VkDeviceSize imageMipTailSize = texture.sparseImageMemoryRequirements.imageMipTailSize; - VkDeviceSize imageMipTailOffset = texture.sparseImageMemoryRequirements.imageMipTailOffset; - // Stride between memory bindings for each mip level if not single mip tail (VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT not set) - VkDeviceSize imageMipTailStride = texture.sparseImageMemoryRequirements.imageMipTailStride; - - VkMemoryAllocateInfo allocInfo = vks::initializers::memoryAllocateInfo(); - allocInfo.allocationSize = imageMipTailSize; - allocInfo.memoryTypeIndex = texture.memoryTypeIndex; - VK_CHECK_RESULT(vkAllocateMemory(device, &allocInfo, nullptr, &texture.mipTailimageMemoryBind.memory)); - - uint32_t mipLevel = texture.sparseImageMemoryRequirements.imageMipTailFirstLod; - uint32_t width = std::max(texture.width >> texture.sparseImageMemoryRequirements.imageMipTailFirstLod, 1u); - uint32_t height = std::max(texture.height >> texture.sparseImageMemoryRequirements.imageMipTailFirstLod, 1u); - uint32_t depth = 1; - - for (uint32_t i = texture.mipTailStart; i < texture.mipLevels; i++) { - - const uint32_t width = std::max(texture.width >> i, 1u); - const uint32_t height = std::max(texture.height >> i, 1u); - - // Generate some random image data and upload as a buffer - const size_t bufferSize = 4 * width * height; - - vks::Buffer imageBuffer; - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &imageBuffer, - bufferSize)); - imageBuffer.map(); - - // Fill buffer with random colors - std::random_device rd; - std::mt19937 rndEngine(rd()); - std::uniform_int_distribution rndDist(0, 255); - uint8_t* data = (uint8_t*)imageBuffer.mapped; - randomPattern(data, width, height); - - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout(copyCmd, texture.image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture.subRange, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - VkBufferImageCopy region{}; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageSubresource.mipLevel = i; - region.imageOffset = {}; - region.imageExtent = { width, height, 1 }; - vkCmdCopyBufferToImage(copyCmd, imageBuffer.buffer, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - vks::tools::setImageLayout(copyCmd, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, texture.subRange, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - vulkanDevice->flushCommandBuffer(copyCmd, queue); - - imageBuffer.destroy(); - } -} - -void VulkanExample::flushRandomPages() -{ - vkDeviceWaitIdle(device); - - std::default_random_engine rndEngine(benchmark.active ? 0 : std::random_device{}()); - std::uniform_real_distribution rndDist(0.0f, 1.0f); - - std::vector updatedPages; - std::vector bindingChangedPages; - for (auto& page : texture.pages) - { - if (rndDist(rndEngine) < 0.5f) { - continue; - } - if (page.imageMemoryBind.memory != VK_NULL_HANDLE){ - page.del = true; - bindingChangedPages.push_back(page); - } - } - - // Update sparse queue binding - texture.updateSparseBindInfo(bindingChangedPages, true); - VkFenceCreateInfo fenceInfo = vks::initializers::fenceCreateInfo(VK_FLAGS_NONE); - VkFence fence; - VK_CHECK_RESULT(vkCreateFence(device, &fenceInfo, nullptr, &fence)); - vkQueueBindSparse(queue, 1, &texture.bindSparseInfo, fence); - vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX); - vkDestroyFence(device, fence, nullptr); - for (auto& page : texture.pages) - { - if (page.del) - { - page.release(device); - } - } -} - -void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) -{ - if (overlay->header("Settings")) { - if (overlay->sliderFloat("LOD bias", &uniformData.lodBias, -(float)texture.mipLevels, (float)texture.mipLevels)) { - updateUniformBuffers(); - } - if (overlay->button("Fill random pages")) { - fillRandomPages(); - } - if (overlay->button("Flush random pages")) { - flushRandomPages(); - } - if (overlay->button("Fill mip tail")) { - fillMipTail(); - } - } - if (overlay->header("Statistics")) { - uint32_t respages = 0; - std::for_each(texture.pages.begin(), texture.pages.end(), [&respages](VirtualTexturePage page) { respages += (page.resident()) ? 1 : 0; }); - overlay->text("Resident pages: %d of %d", respages, static_cast(texture.pages.size())); - overlay->text("Mip tail starts at: %d", texture.mipTailStart); - } - -} - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/texturesparseresidency/texturesparseresidency.h b/examples/texturesparseresidency/texturesparseresidency.h deleted file mode 100644 index 9964b83e..00000000 --- a/examples/texturesparseresidency/texturesparseresidency.h +++ /dev/null @@ -1,120 +0,0 @@ -/* -* Vulkan Example - Sparse texture residency example -* -* Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -/* -* Important note : This sample is work-in-progress and works basically, but it's not finished -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -// Virtual texture page as a part of the partially resident texture -// Contains memory bindings, offsets and status information -struct VirtualTexturePage -{ - VkOffset3D offset; - VkExtent3D extent; - VkSparseImageMemoryBind imageMemoryBind; // Sparse image memory bind for this page - VkDeviceSize size; // Page (memory) size in bytes - uint32_t mipLevel; // Mip level that this page belongs to - uint32_t layer; // Array layer that this page belongs to - uint32_t index; - bool del; - - VirtualTexturePage(); - bool resident(); - bool allocate(VkDevice device, uint32_t memoryTypeIndex); - bool release(VkDevice device); -}; - -// Virtual texture object containing all pages -struct VirtualTexture -{ - VkDevice device; - VkImage image; // Texture image handle - VkBindSparseInfo bindSparseInfo; // Sparse queue binding information - std::vector pages; // Contains all virtual pages of the texture - std::vector sparseImageMemoryBinds; // Sparse image memory bindings of all memory-backed virtual tables - std::vector opaqueMemoryBinds; // Sparse opaque memory bindings for the mip tail (if present) - VkSparseImageMemoryBindInfo imageMemoryBindInfo; // Sparse image memory bind info - VkSparseImageOpaqueMemoryBindInfo opaqueMemoryBindInfo; // Sparse image opaque memory bind info (mip tail) - uint32_t mipTailStart; // First mip level in mip tail - VkSparseImageMemoryRequirements sparseImageMemoryRequirements; // @todo: Comment - uint32_t memoryTypeIndex; // @todo: Comment - - VkSparseImageMemoryBind mipTailimageMemoryBind{}; - - // @todo: comment - struct MipTailInfo { - bool singleMipTail; - bool alingedMipSize; - } mipTailInfo; - - VirtualTexturePage *addPage(VkOffset3D offset, VkExtent3D extent, const VkDeviceSize size, const uint32_t mipLevel, uint32_t layer); - void updateSparseBindInfo(std::vector &bindingChangedPages, bool del = false); - // @todo: replace with dtor? - void destroy(); -}; - -class VulkanExample : public VulkanExampleBase -{ -public: - //todo: comments - struct SparseTexture : VirtualTexture { - VkSampler sampler; - VkImageLayout imageLayout; - VkImageView view; - VkDescriptorImageInfo descriptor; - VkFormat format; - uint32_t width, height; - uint32_t mipLevels; - uint32_t layerCount; - VkImageSubresourceRange subRange; - } texture; - - vkglTF::Model plane; - - struct UniformData { - glm::mat4 projection; - glm::mat4 model; - glm::vec4 viewPos; - float lodBias = 0.0f; - } uniformData; - vks::Buffer uniformBuffer; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - //todo: comment - VkSemaphore bindSparseSemaphore{ VK_NULL_HANDLE }; - - VulkanExample(); - ~VulkanExample(); - virtual void getEnabledFeatures(); - glm::uvec3 alignedDivision(const VkExtent3D& extent, const VkExtent3D& granularity); - void randomPattern(uint8_t* buffer, uint32_t width, uint32_t height); - void prepareSparseTexture(uint32_t width, uint32_t height, uint32_t layerCount, VkFormat format); - // @todo: move to dtor of texture - void destroyTextureImage(SparseTexture texture); - void buildCommandBuffers(); - void draw(); - void loadAssets(); - void setupDescriptors(); - void preparePipelines(); - void prepareUniformBuffers(); - void updateUniformBuffers(); - void prepare(); - virtual void render(); - void uploadContent(VirtualTexturePage page, VkImage image); - void fillRandomPages(); - void fillMipTail(); - void flushRandomPages(); - virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); -}; diff --git a/examples/timelinesemaphore/timelinesemaphore.cpp b/examples/timelinesemaphore/timelinesemaphore.cpp deleted file mode 100644 index 6b9a0c30..00000000 --- a/examples/timelinesemaphore/timelinesemaphore.cpp +++ /dev/null @@ -1,674 +0,0 @@ -/* -* Vulkan Example - Using timeline semaphores -* -* Based on the compute n-nbody sample, this sample replaces multiple semaphores with a single timeline semaphore -* -* Copyright (C) 2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" - -#if defined(__ANDROID__) -// Lower particle count on Android for performance reasons -#define PARTICLES_PER_ATTRACTOR 3 * 1024 -#else -#define PARTICLES_PER_ATTRACTOR 4 * 1024 -#endif - -class VulkanExample : public VulkanExampleBase -{ -public: - struct Textures { - vks::Texture2D particle; - vks::Texture2D gradient; - } textures{}; - - // Particle Definition - struct Particle { - glm::vec4 pos; - glm::vec4 vel; - }; - uint32_t numParticles{ 0 }; - vks::Buffer storageBuffer; - - // Resources for the graphics part of the example - struct Graphics { - uint32_t queueFamilyIndex; - VkDescriptorSetLayout descriptorSetLayout; - VkDescriptorSet descriptorSet; - VkPipelineLayout pipelineLayout; - VkPipeline pipeline; - struct UniformData { - glm::mat4 projection; - glm::mat4 view; - glm::vec2 screenDim; - } uniformData; - vks::Buffer uniformBuffer; - } graphics{}; - - // Resources for the compute part of the example - struct Compute { - uint32_t queueFamilyIndex; - VkQueue queue; - VkCommandPool commandPool; - VkCommandBuffer commandBuffer; - VkDescriptorSetLayout descriptorSetLayout; - VkDescriptorSet descriptorSet; - VkPipelineLayout pipelineLayout; - VkPipeline pipelineCalculate; - VkPipeline pipelineIntegrate; - struct UniformData { - float deltaT{ 0.0f }; - int32_t particleCount{ 0 }; - float gravity{ 0.002f }; - float power{ 0.75f }; - float soften{ 0.05f }; - } uniformData; - vks::Buffer uniformBuffer; - } compute{}; - - // Along with the actual semaphore we also need to track the increasing value of the timeline, - // so we store both in a single struct - struct TimeLineSemaphore { - VkSemaphore handle{ VK_NULL_HANDLE }; - uint64_t value{ 0 }; - } timeLineSemaphore; - - VkPhysicalDeviceTimelineSemaphoreFeaturesKHR enabledTimelineSemaphoreFeaturesKHR{}; - - VulkanExample() : VulkanExampleBase() - { - title = "Timeline semaphores"; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(-26.0f, 75.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -14.0f)); - camera.movementSpeed = 2.5f; - - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME); - - enabledTimelineSemaphoreFeaturesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR; - enabledTimelineSemaphoreFeaturesKHR.timelineSemaphore = VK_TRUE; - - deviceCreatepNextChain = &enabledTimelineSemaphoreFeaturesKHR; - } - - ~VulkanExample() - { - if (device) { - vkDestroySemaphore(device, timeLineSemaphore.handle, nullptr); - - // Graphics - graphics.uniformBuffer.destroy(); - vkDestroyPipeline(device, graphics.pipeline, nullptr); - vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, graphics.descriptorSetLayout, nullptr); - - // Compute - compute.uniformBuffer.destroy(); - vkDestroyPipelineLayout(device, compute.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, compute.descriptorSetLayout, nullptr); - vkDestroyPipeline(device, compute.pipelineCalculate, nullptr); - vkDestroyPipeline(device, compute.pipelineIntegrate, nullptr); - vkDestroyCommandPool(device, compute.commandPool, nullptr); - - storageBuffer.destroy(); - - textures.particle.destroy(); - textures.gradient.destroy(); - } - } - - void loadAssets() - { - textures.particle.loadFromFile(getAssetPath() + "textures/particle01_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - textures.gradient.loadFromFile(getAssetPath() + "textures/particle_gradient_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = { {0.0f, 0.0f, 0.0f, 1.0f} }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - // Acquire barrier - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - 0, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - compute.queueFamilyIndex, - graphics.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - // Draw the particle system using the update vertex buffer - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipeline); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics.pipelineLayout, 0, 1, &graphics.descriptorSet, 0, nullptr); - - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &storageBuffer.buffer, offsets); - vkCmdDraw(drawCmdBuffers[i], numParticles, 1, 0, 0); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - // Release barrier - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - 0, - graphics.queueFamilyIndex, - compute.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - - } - - void buildComputeCommandBuffer() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VK_CHECK_RESULT(vkBeginCommandBuffer(compute.commandBuffer, &cmdBufInfo)); - - // Acquire barrier - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - 0, - VK_ACCESS_SHADER_WRITE_BIT, - graphics.queueFamilyIndex, - compute.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - // First pass: Calculate particle movement - // ------------------------------------------------------------------------------------------------------- - vkCmdBindPipeline(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineCalculate); - vkCmdBindDescriptorSets(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineLayout, 0, 1, &compute.descriptorSet, 0, 0); - vkCmdDispatch(compute.commandBuffer, numParticles / 256, 1, 1); - - // Add memory barrier to ensure that the computer shader has finished writing to the buffer - VkBufferMemoryBarrier bufferBarrier = vks::initializers::bufferMemoryBarrier(); - bufferBarrier.buffer = storageBuffer.buffer; - bufferBarrier.size = storageBuffer.descriptor.range; - bufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - bufferBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - // Transfer ownership if compute and graphics queue family indices differ - bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 1, &bufferBarrier, - 0, nullptr); - - // Second pass: Integrate particles - // ------------------------------------------------------------------------------------------------------- - vkCmdBindPipeline(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineIntegrate); - vkCmdDispatch(compute.commandBuffer, numParticles / 256, 1, 1); - - // Release barrier - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_SHADER_WRITE_BIT, - 0, - compute.queueFamilyIndex, - graphics.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - - vkEndCommandBuffer(compute.commandBuffer); - } - - // Setup and fill the compute shader storage buffers containing the particles - void prepareStorageBuffers() - { - // We mark a few particles as attractors that move along a given path, these will pull in the other particles - std::vector attractors = { - glm::vec3(5.0f, 0.0f, 0.0f), - glm::vec3(-5.0f, 0.0f, 0.0f), - glm::vec3(0.0f, 0.0f, 5.0f), - glm::vec3(0.0f, 0.0f, -5.0f), - glm::vec3(0.0f, 4.0f, 0.0f), - glm::vec3(0.0f, -8.0f, 0.0f), - }; - - numParticles = static_cast(attractors.size()) * PARTICLES_PER_ATTRACTOR; - - // Initial particle positions - std::vector particleBuffer(numParticles); - - std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::normal_distribution rndDist(0.0f, 1.0f); - - for (uint32_t i = 0; i < static_cast(attractors.size()); i++) - { - for (uint32_t j = 0; j < PARTICLES_PER_ATTRACTOR; j++) - { - Particle& particle = particleBuffer[i * PARTICLES_PER_ATTRACTOR + j]; - - // First particle in group as heavy center of gravity - if (j == 0) - { - particle.pos = glm::vec4(attractors[i] * 1.5f, 90000.0f); - particle.vel = glm::vec4(glm::vec4(0.0f)); - } - else - { - // Position - glm::vec3 position(attractors[i] + glm::vec3(rndDist(rndEngine), rndDist(rndEngine), rndDist(rndEngine)) * 0.75f); - float len = glm::length(glm::normalize(position - attractors[i])); - position.y *= 2.0f - (len * len); - - // Velocity - glm::vec3 angular = glm::vec3(0.5f, 1.5f, 0.5f) * (((i % 2) == 0) ? 1.0f : -1.0f); - glm::vec3 velocity = glm::cross((position - attractors[i]), angular) + glm::vec3(rndDist(rndEngine), rndDist(rndEngine), rndDist(rndEngine) * 0.025f); - - float mass = (rndDist(rndEngine) * 0.5f + 0.5f) * 75.0f; - particle.pos = glm::vec4(position, mass); - particle.vel = glm::vec4(velocity, 0.0f); - } - - // Color gradient offset - particle.vel.w = (float)i * 1.0f / static_cast(attractors.size()); - } - } - - compute.uniformData.particleCount = numParticles; - - VkDeviceSize storageBufferSize = particleBuffer.size() * sizeof(Particle); - - // Staging - vks::Buffer stagingBuffer; - vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer, storageBufferSize, particleBuffer.data()); - vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &storageBuffer, storageBufferSize); - - // Copy from staging buffer to storage buffer - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkBufferCopy copyRegion = {}; - copyRegion.size = storageBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, storageBuffer.buffer, 1, ©Region); - // Execute a transfer barrier to the compute queue, if necessary - if (graphics.queueFamilyIndex != compute.queueFamilyIndex) - { - VkBufferMemoryBarrier buffer_barrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - 0, - graphics.queueFamilyIndex, - compute.queueFamilyIndex, - storageBuffer.buffer, - 0, - storageBuffer.size - }; - - vkCmdPipelineBarrier( - copyCmd, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 1, &buffer_barrier, - 0, nullptr); - } - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - stagingBuffer.destroy(); - } - - void prepareGraphics() - { - // Vertex shader uniform buffer block - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &graphics.uniformBuffer, sizeof(Graphics::UniformData)); - VK_CHECK_RESULT(graphics.uniformBuffer.map()); - - // Descriptor pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor layout - std::vector setLayoutBindings; - setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 2), - }; - - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &graphics.descriptorSetLayout)); - - // Descriptor set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &graphics.descriptorSet)); - - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(graphics.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &textures.particle.descriptor), - vks::initializers::writeDescriptorSet(graphics.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.gradient.descriptor), - vks::initializers::writeDescriptorSet(graphics.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &graphics.uniformBuffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - - // Pipeline layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&graphics.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &graphics.pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_ALWAYS); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - // Vertex Input state - std::vector inputBindings = { - vks::initializers::vertexInputBindingDescription(0, sizeof(Particle), VK_VERTEX_INPUT_RATE_VERTEX) - }; - std::vector inputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Particle, pos)), - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Particle, vel)), - }; - VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputState.vertexBindingDescriptionCount = static_cast(inputBindings.size()); - vertexInputState.pVertexBindingDescriptions = inputBindings.data(); - vertexInputState.vertexAttributeDescriptionCount = static_cast(inputAttributes.size()); - vertexInputState.pVertexAttributeDescriptions = inputAttributes.data(); - - // Shaders - shaderStages[0] = loadShader(getShadersPath() + "computenbody/particle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "computenbody/particle.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks::initializers::pipelineCreateInfo(graphics.pipelineLayout, renderPass, 0); - pipelineCreateInfo.pVertexInputState = &vertexInputState; - pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; - pipelineCreateInfo.pRasterizationState = &rasterizationState; - pipelineCreateInfo.pColorBlendState = &colorBlendState; - pipelineCreateInfo.pMultisampleState = &multisampleState; - pipelineCreateInfo.pViewportState = &viewportState; - pipelineCreateInfo.pDepthStencilState = &depthStencilState; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); - pipelineCreateInfo.pStages = shaderStages.data(); - pipelineCreateInfo.renderPass = renderPass; - - // Additive blending - blendAttachmentState.colorWriteMask = 0xF; - blendAttachmentState.blendEnable = VK_TRUE; - blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; - blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; - blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; - - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &graphics.pipeline)); - - buildCommandBuffers(); - } - - void prepareCompute() - { - vkGetDeviceQueue(device, compute.queueFamilyIndex, 0, &compute.queue); - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &compute.uniformBuffer, sizeof(Compute::UniformData)); - VK_CHECK_RESULT(compute.uniformBuffer.map()); - std::vector setLayoutBindings = { - // Binding 0 : Particle position storage buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 0), - // Binding 1 : Uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 1), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &compute.descriptorSetLayout)); - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &compute.descriptorSet)); - std::vector computeWriteDescriptorSets = { - vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &storageBuffer.descriptor), - vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,1,&compute.uniformBuffer.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(computeWriteDescriptorSets.size()), computeWriteDescriptorSets.data(), 0, nullptr); - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&compute.descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &compute.pipelineLayout)); - VkComputePipelineCreateInfo computePipelineCreateInfo = vks::initializers::computePipelineCreateInfo(compute.pipelineLayout, 0); - computePipelineCreateInfo.stage = loadShader(getShadersPath() + "computenbody/particle_calculate.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT); - uint32_t sharedDataSize = std::min((uint32_t)1024, (uint32_t)(vulkanDevice->properties.limits.maxComputeSharedMemorySize / sizeof(glm::vec4))); - VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t)); - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(int32_t), &sharedDataSize); - computePipelineCreateInfo.stage.pSpecializationInfo = &specializationInfo; - VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &compute.pipelineCalculate)); - computePipelineCreateInfo.stage = loadShader(getShadersPath() + "computenbody/particle_integrate.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT); - VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &compute.pipelineIntegrate)); - VkCommandPoolCreateInfo cmdPoolInfo = {}; - cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmdPoolInfo.queueFamilyIndex = compute.queueFamilyIndex; - cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &compute.commandPool)); - compute.commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, compute.commandPool); - buildComputeCommandBuffer(); - } - - void updateComputeUniformBuffers() - { - compute.uniformData.deltaT = paused ? 0.0f : frameTimer * 0.05f; - memcpy(compute.uniformBuffer.mapped, &compute.uniformData, sizeof(Compute::UniformData)); - } - - void updateGraphicsUniformBuffers() - { - graphics.uniformData.projection = camera.matrices.perspective; - graphics.uniformData.view = camera.matrices.view; - graphics.uniformData.screenDim = glm::vec2((float)width, (float)height); - memcpy(graphics.uniformBuffer.mapped, &graphics.uniformData, sizeof(Graphics::UniformData)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - graphics.queueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - compute.queueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - - // Setup the timeline semaphore - VkSemaphoreCreateInfo semaphoreCI{}; - semaphoreCI.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - // It's a variation of the core semaphore type, creation is handled via an extension struture - VkSemaphoreTypeCreateInfoKHR semaphoreTypeCI{}; - semaphoreTypeCI.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR; - semaphoreTypeCI.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE_KHR; - semaphoreTypeCI.initialValue = timeLineSemaphore.value; - - semaphoreCI.pNext = &semaphoreTypeCI; - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &timeLineSemaphore.handle)); - - loadAssets(); - prepareStorageBuffers(); - prepareGraphics(); - prepareCompute(); - prepared = true; - } - - void draw() - { - // Wait for rendering finished - VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - - // Submit compute commands - - // Define incremental timeline sempahore states - const uint64_t graphics_finished = timeLineSemaphore.value; - const uint64_t compute_finished = timeLineSemaphore.value + 1; - const uint64_t all_finished = timeLineSemaphore.value + 2; - - // With timeline semaphores, we can state on what value we want to wait on / signal on - VkTimelineSemaphoreSubmitInfoKHR timeLineSubmitInfo{ VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR }; - timeLineSubmitInfo.waitSemaphoreValueCount = 1; - timeLineSubmitInfo.pWaitSemaphoreValues = &graphics_finished; - timeLineSubmitInfo.signalSemaphoreValueCount = 1; - timeLineSubmitInfo.pSignalSemaphoreValues = &compute_finished; - - VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; - computeSubmitInfo.waitSemaphoreCount = 1; - computeSubmitInfo.pWaitSemaphores = &timeLineSemaphore.handle; - computeSubmitInfo.pWaitDstStageMask = &waitStageMask; - computeSubmitInfo.signalSemaphoreCount = 1; - computeSubmitInfo.pSignalSemaphores = &timeLineSemaphore.handle; - - computeSubmitInfo.pNext = &timeLineSubmitInfo; - - VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::prepareFrame(); - - VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - VkSemaphore graphicsWaitSemaphores[] = { timeLineSemaphore.handle, semaphores.presentComplete }; - VkSemaphore graphicsSignalSemaphores[] = { timeLineSemaphore.handle, semaphores.renderComplete }; - - // Submit graphics commands - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - submitInfo.waitSemaphoreCount = 2; - submitInfo.pWaitSemaphores = graphicsWaitSemaphores; - submitInfo.pWaitDstStageMask = graphicsWaitStageMasks; - submitInfo.signalSemaphoreCount = 2; - submitInfo.pSignalSemaphores = graphicsSignalSemaphores; - - uint64_t wait_values[2] = { compute_finished, compute_finished }; - uint64_t signal_values[2] = { all_finished, all_finished }; - - timeLineSubmitInfo.waitSemaphoreValueCount = 2; - timeLineSubmitInfo.pWaitSemaphoreValues = &wait_values[0]; - timeLineSubmitInfo.signalSemaphoreValueCount = 2; - timeLineSubmitInfo.pSignalSemaphoreValues = &signal_values[0]; - - submitInfo.pNext = &timeLineSubmitInfo; - - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - // Increase timeline value base for next frame - timeLineSemaphore.value = all_finished; - - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateComputeUniformBuffers(); - updateGraphicsUniformBuffers(); - draw(); - } -}; - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/triangle/triangle.cpp b/examples/triangle/triangle.cpp deleted file mode 100644 index 22bb8f3f..00000000 --- a/examples/triangle/triangle.cpp +++ /dev/null @@ -1,1186 +0,0 @@ -/* -* Vulkan Example - Basic indexed triangle rendering -* -* Note: -* This is a "pedal to the metal" example to show off how to get Vulkan up and displaying something -* Contrary to the other examples, this one won't make use of helper functions or initializers -* Except in a few cases (swap chain setup e.g.) -* -* Copyright (C) 2016-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include -#include -#include -#include -#include -#include -#include - -#define GLM_FORCE_RADIANS -#define GLM_FORCE_DEPTH_ZERO_TO_ONE -#include -#include - -#include -#include "vulkanexamplebase.h" - -// We want to keep GPU and CPU busy. To do that we may start building a new command buffer while the previous one is still being executed -// This number defines how many frames may be worked on simultaneously at once -// Increasing this number may improve performance but will also introduce additional latency -#define MAX_CONCURRENT_FRAMES 2 - -class VulkanExample : public VulkanExampleBase -{ -public: - // Vertex layout used in this example - struct Vertex { - float position[3]; - float color[3]; - }; - - // Vertex buffer and attributes - struct { - VkDeviceMemory memory{ VK_NULL_HANDLE }; // Handle to the device memory for this buffer - VkBuffer buffer{ VK_NULL_HANDLE }; // Handle to the Vulkan buffer object that the memory is bound to - } vertices; - - // Index buffer - struct { - VkDeviceMemory memory{ VK_NULL_HANDLE }; - VkBuffer buffer{ VK_NULL_HANDLE }; - uint32_t count{ 0 }; - } indices; - - // Uniform buffer block object - struct UniformBuffer { - VkDeviceMemory memory{ VK_NULL_HANDLE }; - VkBuffer buffer{ VK_NULL_HANDLE }; - // The descriptor set stores the resources bound to the binding points in a shader - // It connects the binding points of the different shaders with the buffers and images used for those bindings - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - // We keep a pointer to the mapped buffer, so we can easily update it's contents via a memcpy - uint8_t* mapped{ nullptr }; - }; - // We use one UBO per frame, so we can have a frame overlap and make sure that uniforms aren't updated while still in use - std::array uniformBuffers; - - // For simplicity we use the same uniform block layout as in the shader: - // - // layout(set = 0, binding = 0) uniform UBO - // { - // mat4 projectionMatrix; - // mat4 modelMatrix; - // mat4 viewMatrix; - // } ubo; - // - // This way we can just memcopy the ubo data to the ubo - // Note: You should use data types that align with the GPU in order to avoid manual padding (vec4, mat4) - struct ShaderData { - glm::mat4 projectionMatrix; - glm::mat4 modelMatrix; - glm::mat4 viewMatrix; - }; - - // The pipeline layout is used by a pipeline to access the descriptor sets - // It defines interface (without binding any actual data) between the shader stages used by the pipeline and the shader resources - // A pipeline layout can be shared among multiple pipelines as long as their interfaces match - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - - // Pipelines (often called "pipeline state objects") are used to bake all states that affect a pipeline - // While in OpenGL every state can be changed at (almost) any time, Vulkan requires to layout the graphics (and compute) pipeline states upfront - // So for each combination of non-dynamic pipeline states you need a new pipeline (there are a few exceptions to this not discussed here) - // Even though this adds a new dimension of planning ahead, it's a great opportunity for performance optimizations by the driver - VkPipeline pipeline{ VK_NULL_HANDLE }; - - // The descriptor set layout describes the shader binding layout (without actually referencing descriptor) - // Like the pipeline layout it's pretty much a blueprint and can be used with different descriptor sets as long as their layout matches - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - // Synchronization primitives - // Synchronization is an important concept of Vulkan that OpenGL mostly hid away. Getting this right is crucial to using Vulkan. - - // Semaphores are used to coordinate operations within the graphics queue and ensure correct command ordering - std::vector presentCompleteSemaphores{}; - std::vector renderCompleteSemaphores{}; - - VkCommandPool commandPool{ VK_NULL_HANDLE }; - std::array commandBuffers{}; - std::array waitFences{}; - - // To select the correct sync and command objects, we need to keep track of the current frame - uint32_t currentFrame{ 0 }; - - VulkanExample() : VulkanExampleBase() - { - title = "Basic indexed triangle"; - // To keep things simple, we don't use the UI overlay from the framework - settings.overlay = false; - // Setup a default look-at camera - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -2.5f)); - camera.setRotation(glm::vec3(0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 1.0f, 256.0f); - // Values not set here are initialized in the base class constructor - } - - ~VulkanExample() override - { - // Clean up used Vulkan resources - // Note: Inherited destructor cleans up resources stored in base class - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyBuffer(device, vertices.buffer, nullptr); - vkFreeMemory(device, vertices.memory, nullptr); - vkDestroyBuffer(device, indices.buffer, nullptr); - vkFreeMemory(device, indices.memory, nullptr); - vkDestroyCommandPool(device, commandPool, nullptr); - for (size_t i = 0; i < presentCompleteSemaphores.size(); i++) { - vkDestroySemaphore(device, presentCompleteSemaphores[i], nullptr); - } - for (size_t i = 0; i < renderCompleteSemaphores.size(); i++) { - vkDestroySemaphore(device, renderCompleteSemaphores[i], nullptr); - } - for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) { - vkDestroyFence(device, waitFences[i], nullptr); - vkDestroyBuffer(device, uniformBuffers[i].buffer, nullptr); - vkFreeMemory(device, uniformBuffers[i].memory, nullptr); - } - } - } - - // This function is used to request a device memory type that supports all the property flags we request (e.g. device local, host visible) - // Upon success it will return the index of the memory type that fits our requested memory properties - // This is necessary as implementations can offer an arbitrary number of memory types with different - // memory properties. - // You can check https://vulkan.gpuinfo.org/ for details on different memory configurations - uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) - { - // Iterate over all memory types available for the device used in this example - for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++) - { - if ((typeBits & 1) == 1) - { - if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) - { - return i; - } - } - typeBits >>= 1; - } - - throw "Could not find a suitable memory type!"; - } - - // Create the per-frame (in flight) Vulkan synchronization primitives used in this example - void createSynchronizationPrimitives() - { - // Fences are used to check draw command buffer completion on the host - for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) { - VkFenceCreateInfo fenceCI{}; - fenceCI.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - // Create the fences in signaled state (so we don't wait on first render of each command buffer) - fenceCI.flags = VK_FENCE_CREATE_SIGNALED_BIT; - // Fence used to ensure that command buffer has completed exection before using it again - VK_CHECK_RESULT(vkCreateFence(device, &fenceCI, nullptr, &waitFences[i])); - } - // Semaphores are used for correct command ordering within a queue - // Used to ensure that image presentation is complete before starting to submit again - presentCompleteSemaphores.resize(MAX_CONCURRENT_FRAMES); - for (auto& semaphore : presentCompleteSemaphores) { - VkSemaphoreCreateInfo semaphoreCI{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &semaphore)); - } - // Render completion - // Semaphore used to ensure that all commands submitted have been finished before submitting the image to the queue - renderCompleteSemaphores.resize(swapChain.images.size()); - for (auto& semaphore : renderCompleteSemaphores) { - VkSemaphoreCreateInfo semaphoreCI{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &semaphore)); - } - } - - void createCommandBuffers() - { - // All command buffers are allocated from a command pool - VkCommandPoolCreateInfo commandPoolCI{}; - commandPoolCI.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - commandPoolCI.queueFamilyIndex = swapChain.queueNodeIndex; - commandPoolCI.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &commandPoolCI, nullptr, &commandPool)); - - // Allocate one command buffer per max. concurrent frame from above pool - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, MAX_CONCURRENT_FRAMES); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commandBuffers.data())); - } - - // Prepare vertex and index buffers for an indexed triangle - // Also uploads them to device local memory using staging and initializes vertex input and attribute binding to match the vertex shader - void createVertexBuffer() - { - // A note on memory management in Vulkan in general: - // This is a very complex topic and while it's fine for an example application to small individual memory allocations that is not - // what should be done a real-world application, where you should allocate large chunks of memory at once instead. - - // Setup vertices - std::vector vertexBuffer{ - { { 1.0f, 1.0f, 0.0f }, { 1.0f, 0.0f, 0.0f } }, - { { -1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } }, - { { 0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } } - }; - uint32_t vertexBufferSize = static_cast(vertexBuffer.size()) * sizeof(Vertex); - - // Setup indices - std::vector indexBuffer{ 0, 1, 2 }; - indices.count = static_cast(indexBuffer.size()); - uint32_t indexBufferSize = indices.count * sizeof(uint32_t); - - VkMemoryAllocateInfo memAlloc{}; - memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - VkMemoryRequirements memReqs; - - // Static data like vertex and index buffer should be stored on the device memory for optimal (and fastest) access by the GPU - // - // To achieve this we use so-called "staging buffers" : - // - Create a buffer that's visible to the host (and can be mapped) - // - Copy the data to this buffer - // - Create another buffer that's local on the device (VRAM) with the same size - // - Copy the data from the host to the device using a command buffer - // - Delete the host visible (staging) buffer - // - Use the device local buffers for rendering - // - // Note: On unified memory architectures where host (CPU) and GPU share the same memory, staging is not necessary - // To keep this sample easy to follow, there is no check for that in place - - struct StagingBuffer { - VkDeviceMemory memory; - VkBuffer buffer; - }; - - struct { - StagingBuffer vertices; - StagingBuffer indices; - } stagingBuffers{}; - - void* data; - - // Vertex buffer - VkBufferCreateInfo vertexBufferInfoCI{}; - vertexBufferInfoCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - vertexBufferInfoCI.size = vertexBufferSize; - // Buffer is used as the copy source - vertexBufferInfoCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - // Create a host-visible buffer to copy the vertex data to (staging buffer) - VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfoCI, nullptr, &stagingBuffers.vertices.buffer)); - vkGetBufferMemoryRequirements(device, stagingBuffers.vertices.buffer, &memReqs); - memAlloc.allocationSize = memReqs.size; - // Request a host visible memory type that can be used to copy our data to - // Also request it to be coherent, so that writes are visible to the GPU right after unmapping the buffer - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffers.vertices.memory)); - // Map and copy - VK_CHECK_RESULT(vkMapMemory(device, stagingBuffers.vertices.memory, 0, memAlloc.allocationSize, 0, &data)); - memcpy(data, vertexBuffer.data(), vertexBufferSize); - vkUnmapMemory(device, stagingBuffers.vertices.memory); - VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffers.vertices.buffer, stagingBuffers.vertices.memory, 0)); - - // Create a device local buffer to which the (host local) vertex data will be copied and which will be used for rendering - vertexBufferInfoCI.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfoCI, nullptr, &vertices.buffer)); - vkGetBufferMemoryRequirements(device, vertices.buffer, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &vertices.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, vertices.buffer, vertices.memory, 0)); - - // Index buffer - VkBufferCreateInfo indexbufferCI{}; - indexbufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - indexbufferCI.size = indexBufferSize; - indexbufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - // Copy index data to a buffer visible to the host (staging buffer) - VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferCI, nullptr, &stagingBuffers.indices.buffer)); - vkGetBufferMemoryRequirements(device, stagingBuffers.indices.buffer, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffers.indices.memory)); - VK_CHECK_RESULT(vkMapMemory(device, stagingBuffers.indices.memory, 0, indexBufferSize, 0, &data)); - memcpy(data, indexBuffer.data(), indexBufferSize); - vkUnmapMemory(device, stagingBuffers.indices.memory); - VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffers.indices.buffer, stagingBuffers.indices.memory, 0)); - - // Create destination buffer with device only visibility - indexbufferCI.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferCI, nullptr, &indices.buffer)); - vkGetBufferMemoryRequirements(device, indices.buffer, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &indices.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, indices.buffer, indices.memory, 0)); - - // Buffer copies have to be submitted to a queue, so we need a command buffer for them - // Note: Some devices offer a dedicated transfer queue (with only the transfer bit set) that may be faster when doing lots of copies - VkCommandBuffer copyCmd; - - VkCommandBufferAllocateInfo cmdBufAllocateInfo{}; - cmdBufAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cmdBufAllocateInfo.commandPool = commandPool; - cmdBufAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cmdBufAllocateInfo.commandBufferCount = 1; - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, ©Cmd)); - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo)); - // Put buffer region copies into command buffer - VkBufferCopy copyRegion{}; - // Vertex buffer - copyRegion.size = vertexBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffers.vertices.buffer, vertices.buffer, 1, ©Region); - // Index buffer - copyRegion.size = indexBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffers.indices.buffer, indices.buffer, 1, ©Region); - VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd)); - - // Submit the command buffer to the queue to finish the copy - VkSubmitInfo submitInfo{}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = ©Cmd; - - // Create fence to ensure that the command buffer has finished executing - VkFenceCreateInfo fenceCI{}; - fenceCI.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fenceCI.flags = 0; - VkFence fence; - VK_CHECK_RESULT(vkCreateFence(device, &fenceCI, nullptr, &fence)); - - // Submit to the queue - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence)); - // Wait for the fence to signal that command buffer has finished executing - VK_CHECK_RESULT(vkWaitForFences(device, 1, &fence, VK_TRUE, DEFAULT_FENCE_TIMEOUT)); - - vkDestroyFence(device, fence, nullptr); - vkFreeCommandBuffers(device, commandPool, 1, ©Cmd); - - // Destroy staging buffers - // Note: Staging buffer must not be deleted before the copies have been submitted and executed - vkDestroyBuffer(device, stagingBuffers.vertices.buffer, nullptr); - vkFreeMemory(device, stagingBuffers.vertices.memory, nullptr); - vkDestroyBuffer(device, stagingBuffers.indices.buffer, nullptr); - vkFreeMemory(device, stagingBuffers.indices.memory, nullptr); - } - - // Descriptors are allocated from a pool, that tells the implementation how many and what types of descriptors we are going to use (at maximum) - void createDescriptorPool() - { - // We need to tell the API the number of max. requested descriptors per type - VkDescriptorPoolSize descriptorTypeCounts[1]{}; - // This example only one descriptor type (uniform buffer) - descriptorTypeCounts[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - // We have one buffer (and as such descriptor) per frame - descriptorTypeCounts[0].descriptorCount = MAX_CONCURRENT_FRAMES; - // For additional types you need to add new entries in the type count list - // E.g. for two combined image samplers : - // typeCounts[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - // typeCounts[1].descriptorCount = 2; - - // Create the global descriptor pool - // All descriptors used in this example are allocated from this pool - VkDescriptorPoolCreateInfo descriptorPoolCI{}; - descriptorPoolCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - descriptorPoolCI.pNext = nullptr; - descriptorPoolCI.poolSizeCount = 1; - descriptorPoolCI.pPoolSizes = descriptorTypeCounts; - // Set the max. number of descriptor sets that can be requested from this pool (requesting beyond this limit will result in an error) - // Our sample will create one set per uniform buffer per frame - descriptorPoolCI.maxSets = MAX_CONCURRENT_FRAMES; - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorPool)); - } - - // Descriptor set layouts define the interface between our application and the shader - // Basically connects the different shader stages to descriptors for binding uniform buffers, image samplers, etc. - // So every shader binding should map to one descriptor set layout binding - void createDescriptorSetLayout() - { - // Binding 0: Uniform buffer (Vertex shader) - VkDescriptorSetLayoutBinding layoutBinding{}; - layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - layoutBinding.descriptorCount = 1; - layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - layoutBinding.pImmutableSamplers = nullptr; - - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI{}; - descriptorLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptorLayoutCI.pNext = nullptr; - descriptorLayoutCI.bindingCount = 1; - descriptorLayoutCI.pBindings = &layoutBinding; - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayout)); - } - - // Shaders access data using descriptor sets that "point" at our uniform buffers - // The descriptor sets make use of the descriptor set layouts created above - void createDescriptorSets() - { - // Allocate one descriptor set per frame from the global descriptor pool - for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) { - VkDescriptorSetAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocInfo.descriptorPool = descriptorPool; - allocInfo.descriptorSetCount = 1; - allocInfo.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &uniformBuffers[i].descriptorSet)); - - // Update the descriptor set determining the shader binding points - // For every binding point used in a shader there needs to be one - // descriptor set matching that binding point - VkWriteDescriptorSet writeDescriptorSet{}; - - // The buffer's information is passed using a descriptor info structure - VkDescriptorBufferInfo bufferInfo{}; - bufferInfo.buffer = uniformBuffers[i].buffer; - bufferInfo.range = sizeof(ShaderData); - - // Binding 0 : Uniform buffer - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.dstSet = uniformBuffers[i].descriptorSet; - writeDescriptorSet.descriptorCount = 1; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - writeDescriptorSet.pBufferInfo = &bufferInfo; - writeDescriptorSet.dstBinding = 0; - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - } - - // Create the depth (and stencil) buffer attachments used by our framebuffers - // Note: Override of virtual function in the base class and called from within VulkanExampleBase::prepare - void setupDepthStencil() override - { - // Create an optimal image used as the depth stencil attachment - VkImageCreateInfo imageCI{}; - imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = depthFormat; - // Use example's height and width - imageCI.extent = { width, height, 1 }; - imageCI.mipLevels = 1; - imageCI.arrayLayers = 1; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &depthStencil.image)); - - // Allocate memory for the image (device local) and bind it to our image - VkMemoryAllocateInfo memAlloc{}; - memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, depthStencil.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depthStencil.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, depthStencil.image, depthStencil.memory, 0)); - - // Create a view for the depth stencil image - // Images aren't directly accessed in Vulkan, but rather through views described by a subresource range - // This allows for multiple views of one image with differing ranges (e.g. for different layers) - VkImageViewCreateInfo depthStencilViewCI{}; - depthStencilViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - depthStencilViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilViewCI.format = depthFormat; - depthStencilViewCI.subresourceRange = {}; - depthStencilViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - // Stencil aspect should only be set on depth + stencil formats (VK_FORMAT_D16_UNORM_S8_UINT..VK_FORMAT_D32_SFLOAT_S8_UINT) - if (depthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) { - depthStencilViewCI.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - depthStencilViewCI.subresourceRange.baseMipLevel = 0; - depthStencilViewCI.subresourceRange.levelCount = 1; - depthStencilViewCI.subresourceRange.baseArrayLayer = 0; - depthStencilViewCI.subresourceRange.layerCount = 1; - depthStencilViewCI.image = depthStencil.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilViewCI, nullptr, &depthStencil.view)); - } - - // Create a frame buffer for each swap chain image - // Note: Override of virtual function in the base class and called from within VulkanExampleBase::prepare - void setupFrameBuffer() override - { - // Create a frame buffer for every image in the swapchain - frameBuffers.resize(swapChain.images.size()); - for (size_t i = 0; i < frameBuffers.size(); i++) - { - std::array attachments{}; - // Color attachment is the view of the swapchain image - attachments[0] = swapChain.imageViews[i]; - // Depth/Stencil attachment is the same for all frame buffers due to how depth works with current GPUs - attachments[1] = depthStencil.view; - - VkFramebufferCreateInfo frameBufferCI{}; - frameBufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - // All frame buffers use the same renderpass setup - frameBufferCI.renderPass = renderPass; - frameBufferCI.attachmentCount = static_cast(attachments.size()); - frameBufferCI.pAttachments = attachments.data(); - frameBufferCI.width = width; - frameBufferCI.height = height; - frameBufferCI.layers = 1; - // Create the framebuffer - VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCI, nullptr, &frameBuffers[i])); - } - } - - // Render pass setup - // Render passes are a new concept in Vulkan. They describe the attachments used during rendering and may contain multiple subpasses with attachment dependencies - // This allows the driver to know up-front what the rendering will look like and is a good opportunity to optimize especially on tile-based renderers (with multiple subpasses) - // Using sub pass dependencies also adds implicit layout transitions for the attachment used, so we don't need to add explicit image memory barriers to transform them - // Note: Override of virtual function in the base class and called from within VulkanExampleBase::prepare - void setupRenderPass() override - { - // This example will use a single render pass with one subpass - - // Descriptors for the attachments used by this renderpass - std::array attachments{}; - - // Color attachment - attachments[0].format = swapChain.colorFormat; // Use the color format selected by the swapchain - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; // We don't use multi sampling in this example - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear this attachment at the start of the render pass - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // Keep its contents after the render pass is finished (for displaying it) - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // We don't use stencil, so don't care for load - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // Same for store - attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Layout at render pass start. Initial doesn't matter, so we use undefined - attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; // Layout to which the attachment is transitioned when the render pass is finished - // As we want to present the color buffer to the swapchain, we transition to PRESENT_KHR - // Depth attachment - attachments[1].format = depthFormat; // A proper depth format is selected in the example base - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at start of first subpass - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // We don't need depth after render pass has finished (DONT_CARE may result in better performance) - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // No stencil - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // No Stencil - attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Layout at render pass start. Initial doesn't matter, so we use undefined - attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Transition to depth/stencil attachment - - // Setup attachment references - VkAttachmentReference colorReference{}; - colorReference.attachment = 0; // Attachment 0 is color - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // Attachment layout used as color during the subpass - - VkAttachmentReference depthReference{}; - depthReference.attachment = 1; // Attachment 1 is color - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Attachment used as depth/stencil used during the subpass - - // Setup a single subpass reference - VkSubpassDescription subpassDescription{}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; // Subpass uses one color attachment - subpassDescription.pColorAttachments = &colorReference; // Reference to the color attachment in slot 0 - subpassDescription.pDepthStencilAttachment = &depthReference; // Reference to the depth attachment in slot 1 - subpassDescription.inputAttachmentCount = 0; // Input attachments can be used to sample from contents of a previous subpass - subpassDescription.pInputAttachments = nullptr; // (Input attachments not used by this example) - subpassDescription.preserveAttachmentCount = 0; // Preserved attachments can be used to loop (and preserve) attachments through subpasses - subpassDescription.pPreserveAttachments = nullptr; // (Preserve attachments not used by this example) - subpassDescription.pResolveAttachments = nullptr; // Resolve attachments are resolved at the end of a sub pass and can be used for e.g. multi sampling - - // Setup subpass dependencies - // These will add the implicit attachment layout transitions specified by the attachment descriptions - // The actual usage layout is preserved through the layout specified in the attachment reference - // Each subpass dependency will introduce a memory and execution dependency between the source and dest subpass described by - // srcStageMask, dstStageMask, srcAccessMask, dstAccessMask (and dependencyFlags is set) - // Note: VK_SUBPASS_EXTERNAL is a special constant that refers to all commands executed outside of the actual renderpass) - std::array dependencies{}; - - // Does the transition from final to initial layout for the depth an color attachments - // Depth attachment - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; - dependencies[0].dependencyFlags = 0; - // Color attachment - dependencies[1].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].dstSubpass = 0; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].srcAccessMask = 0; - dependencies[1].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - dependencies[1].dependencyFlags = 0; - - // Create the actual renderpass - VkRenderPassCreateInfo renderPassCI{}; - renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassCI.attachmentCount = static_cast(attachments.size()); // Number of attachments used by this render pass - renderPassCI.pAttachments = attachments.data(); // Descriptions of the attachments used by the render pass - renderPassCI.subpassCount = 1; // We only use one subpass in this example - renderPassCI.pSubpasses = &subpassDescription; // Description of that subpass - renderPassCI.dependencyCount = static_cast(dependencies.size()); // Number of subpass dependencies - renderPassCI.pDependencies = dependencies.data(); // Subpass dependencies used by the render pass - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderPass)); - } - - // Vulkan loads its shaders from an immediate binary representation called SPIR-V - // Shaders are compiled offline from e.g. GLSL using the reference glslang compiler - // This function loads such a shader from a binary file and returns a shader module structure - VkShaderModule loadSPIRVShader(const std::string& filename) - { - size_t shaderSize; - char* shaderCode{ nullptr }; - -#if defined(__ANDROID__) - // Load shader from compressed asset - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); - assert(asset); - shaderSize = AAsset_getLength(asset); - assert(shaderSize > 0); - - shaderCode = new char[shaderSize]; - AAsset_read(asset, shaderCode, shaderSize); - AAsset_close(asset); -#else - std::ifstream is(filename, std::ios::binary | std::ios::in | std::ios::ate); - - if (is.is_open()) - { - shaderSize = is.tellg(); - is.seekg(0, std::ios::beg); - // Copy file contents into a buffer - shaderCode = new char[shaderSize]; - is.read(shaderCode, shaderSize); - is.close(); - assert(shaderSize > 0); - } -#endif - if (shaderCode) - { - // Create a new shader module that will be used for pipeline creation - VkShaderModuleCreateInfo shaderModuleCI{}; - shaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shaderModuleCI.codeSize = shaderSize; - shaderModuleCI.pCode = (uint32_t*)shaderCode; - - VkShaderModule shaderModule; - VK_CHECK_RESULT(vkCreateShaderModule(device, &shaderModuleCI, nullptr, &shaderModule)); - - delete[] shaderCode; - - return shaderModule; - } - else - { - std::cerr << "Error: Could not open shader file \"" << filename << "\"" << std::endl; - return VK_NULL_HANDLE; - } - } - - void createPipelines() - { - // Create the pipeline layout that is used to generate the rendering pipelines that are based on this descriptor set layout - // In a more complex scenario you would have different pipeline layouts for different descriptor set layouts that could be reused - VkPipelineLayoutCreateInfo pipelineLayoutCI{}; - pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutCI.pNext = nullptr; - pipelineLayoutCI.setLayoutCount = 1; - pipelineLayoutCI.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Create the graphics pipeline used in this example - // Vulkan uses the concept of rendering pipelines to encapsulate fixed states, replacing OpenGL's complex state machine - // A pipeline is then stored and hashed on the GPU making pipeline changes very fast - // Note: There are still a few dynamic states that are not directly part of the pipeline (but the info that they are used is) - - VkGraphicsPipelineCreateInfo pipelineCI{}; - pipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - // The layout used for this pipeline (can be shared among multiple pipelines using the same layout) - pipelineCI.layout = pipelineLayout; - // Renderpass this pipeline is attached to - pipelineCI.renderPass = renderPass; - - // Construct the different states making up the pipeline - - // Input assembly state describes how primitives are assembled - // This pipeline will assemble vertex data as a triangle lists (though we only use one triangle) - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI{}; - inputAssemblyStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssemblyStateCI.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - - // Rasterization state - VkPipelineRasterizationStateCreateInfo rasterizationStateCI{}; - rasterizationStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizationStateCI.polygonMode = VK_POLYGON_MODE_FILL; - rasterizationStateCI.cullMode = VK_CULL_MODE_NONE; - rasterizationStateCI.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterizationStateCI.depthClampEnable = VK_FALSE; - rasterizationStateCI.rasterizerDiscardEnable = VK_FALSE; - rasterizationStateCI.depthBiasEnable = VK_FALSE; - rasterizationStateCI.lineWidth = 1.0f; - - // Color blend state describes how blend factors are calculated (if used) - // We need one blend attachment state per color attachment (even if blending is not used) - VkPipelineColorBlendAttachmentState blendAttachmentState{}; - blendAttachmentState.colorWriteMask = 0xf; - blendAttachmentState.blendEnable = VK_FALSE; - VkPipelineColorBlendStateCreateInfo colorBlendStateCI{}; - colorBlendStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorBlendStateCI.attachmentCount = 1; - colorBlendStateCI.pAttachments = &blendAttachmentState; - - // Viewport state sets the number of viewports and scissor used in this pipeline - // Note: This is actually overridden by the dynamic states (see below) - VkPipelineViewportStateCreateInfo viewportStateCI{}; - viewportStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportStateCI.viewportCount = 1; - viewportStateCI.scissorCount = 1; - - // Enable dynamic states - // Most states are baked into the pipeline, but there are still a few dynamic states that can be changed within a command buffer - // To be able to change these we need do specify which dynamic states will be changed using this pipeline. Their actual states are set later on in the command buffer. - // For this example we will set the viewport and scissor using dynamic states - std::vector dynamicStateEnables; - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_VIEWPORT); - dynamicStateEnables.push_back(VK_DYNAMIC_STATE_SCISSOR); - VkPipelineDynamicStateCreateInfo dynamicStateCI{}; - dynamicStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamicStateCI.pDynamicStates = dynamicStateEnables.data(); - dynamicStateCI.dynamicStateCount = static_cast(dynamicStateEnables.size()); - - // Depth and stencil state containing depth and stencil compare and test operations - // We only use depth tests and want depth tests and writes to be enabled and compare with less or equal - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI{}; - depthStencilStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthStencilStateCI.depthTestEnable = VK_TRUE; - depthStencilStateCI.depthWriteEnable = VK_TRUE; - depthStencilStateCI.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; - depthStencilStateCI.depthBoundsTestEnable = VK_FALSE; - depthStencilStateCI.back.failOp = VK_STENCIL_OP_KEEP; - depthStencilStateCI.back.passOp = VK_STENCIL_OP_KEEP; - depthStencilStateCI.back.compareOp = VK_COMPARE_OP_ALWAYS; - depthStencilStateCI.stencilTestEnable = VK_FALSE; - depthStencilStateCI.front = depthStencilStateCI.back; - - // Multi sampling state - // This example does not make use of multi sampling (for anti-aliasing), the state must still be set and passed to the pipeline - VkPipelineMultisampleStateCreateInfo multisampleStateCI{}; - multisampleStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampleStateCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisampleStateCI.pSampleMask = nullptr; - - // Vertex input descriptions - // Specifies the vertex input parameters for a pipeline - - // Vertex input binding - // This example uses a single vertex input binding at binding point 0 (see vkCmdBindVertexBuffers) - VkVertexInputBindingDescription vertexInputBinding{}; - vertexInputBinding.binding = 0; - vertexInputBinding.stride = sizeof(Vertex); - vertexInputBinding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - // Input attribute bindings describe shader attribute locations and memory layouts - std::array vertexInputAttributs{}; - // These match the following shader layout (see triangle.vert): - // layout (location = 0) in vec3 inPos; - // layout (location = 1) in vec3 inColor; - // Attribute location 0: Position - vertexInputAttributs[0].binding = 0; - vertexInputAttributs[0].location = 0; - // Position attribute is three 32 bit signed (SFLOAT) floats (R32 G32 B32) - vertexInputAttributs[0].format = VK_FORMAT_R32G32B32_SFLOAT; - vertexInputAttributs[0].offset = offsetof(Vertex, position); - // Attribute location 1: Color - vertexInputAttributs[1].binding = 0; - vertexInputAttributs[1].location = 1; - // Color attribute is three 32 bit signed (SFLOAT) floats (R32 G32 B32) - vertexInputAttributs[1].format = VK_FORMAT_R32G32B32_SFLOAT; - vertexInputAttributs[1].offset = offsetof(Vertex, color); - - // Vertex input state used for pipeline creation - VkPipelineVertexInputStateCreateInfo vertexInputStateCI{}; - vertexInputStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputStateCI.vertexBindingDescriptionCount = 1; - vertexInputStateCI.pVertexBindingDescriptions = &vertexInputBinding; - vertexInputStateCI.vertexAttributeDescriptionCount = 2; - vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributs.data(); - - // Shaders - std::array shaderStages{}; - - // Vertex shader - shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - // Set pipeline stage for this shader - shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - // Load binary SPIR-V shader - shaderStages[0].module = loadSPIRVShader(getShadersPath() + "triangle/triangle.vert.spv"); - // Main entry point for the shader - shaderStages[0].pName = "main"; - assert(shaderStages[0].module != VK_NULL_HANDLE); - - // Fragment shader - shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - // Set pipeline stage for this shader - shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - // Load binary SPIR-V shader - shaderStages[1].module = loadSPIRVShader(getShadersPath() + "triangle/triangle.frag.spv"); - // Main entry point for the shader - shaderStages[1].pName = "main"; - assert(shaderStages[1].module != VK_NULL_HANDLE); - - // Set pipeline shader stage info - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Assign the pipeline states to the pipeline creation info structure - pipelineCI.pVertexInputState = &vertexInputStateCI; - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - - // Create rendering pipeline using the specified states - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - - // Shader modules are no longer needed once the graphics pipeline has been created - vkDestroyShaderModule(device, shaderStages[0].module, nullptr); - vkDestroyShaderModule(device, shaderStages[1].module, nullptr); - } - - void createUniformBuffers() - { - // Prepare and initialize the per-frame uniform buffer blocks containing shader uniforms - // Single uniforms like in OpenGL are no longer present in Vulkan. All hader uniforms are passed via uniform buffer blocks - VkMemoryRequirements memReqs; - - // Vertex shader uniform buffer block - VkBufferCreateInfo bufferInfo{}; - VkMemoryAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.pNext = nullptr; - allocInfo.allocationSize = 0; - allocInfo.memoryTypeIndex = 0; - - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = sizeof(ShaderData); - // This buffer will be used as a uniform buffer - bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - - // Create the buffers - for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) { - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferInfo, nullptr, &uniformBuffers[i].buffer)); - // Get memory requirements including size, alignment and memory type - vkGetBufferMemoryRequirements(device, uniformBuffers[i].buffer, &memReqs); - allocInfo.allocationSize = memReqs.size; - // Get the memory type index that supports host visible memory access - // Most implementations offer multiple memory types and selecting the correct one to allocate memory from is crucial - // We also want the buffer to be host coherent so we don't have to flush (or sync after every update. - // Note: This may affect performance so you might not want to do this in a real world application that updates buffers on a regular base - allocInfo.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - // Allocate memory for the uniform buffer - VK_CHECK_RESULT(vkAllocateMemory(device, &allocInfo, nullptr, &(uniformBuffers[i].memory))); - // Bind memory to buffer - VK_CHECK_RESULT(vkBindBufferMemory(device, uniformBuffers[i].buffer, uniformBuffers[i].memory, 0)); - // We map the buffer once, so we can update it without having to map it again - VK_CHECK_RESULT(vkMapMemory(device, uniformBuffers[i].memory, 0, sizeof(ShaderData), 0, (void**)&uniformBuffers[i].mapped)); - } - - } - - void prepare() override - { - VulkanExampleBase::prepare(); - createSynchronizationPrimitives(); - createCommandBuffers(); - createVertexBuffer(); - createUniformBuffers(); - createDescriptorSetLayout(); - createDescriptorPool(); - createDescriptorSets(); - createPipelines(); - prepared = true; - } - - void render() override - { - if (!prepared) - return; - - // Use a fence to wait until the command buffer has finished execution before using it again - vkWaitForFences(device, 1, &waitFences[currentFrame], VK_TRUE, UINT64_MAX); - VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[currentFrame])); - - // Get the next swap chain image from the implementation - // Note that the implementation is free to return the images in any order, so we must use the acquire function and can't just cycle through the images/imageIndex on our own - uint32_t imageIndex; - VkResult result = vkAcquireNextImageKHR(device, swapChain.swapChain, UINT64_MAX, presentCompleteSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); - if (result == VK_ERROR_OUT_OF_DATE_KHR) { - windowResize(); - return; - } - else if ((result != VK_SUCCESS) && (result != VK_SUBOPTIMAL_KHR)) { - throw "Could not acquire the next swap chain image!"; - } - - // Update the uniform buffer for the next frame - ShaderData shaderData{}; - shaderData.projectionMatrix = camera.matrices.perspective; - shaderData.viewMatrix = camera.matrices.view; - shaderData.modelMatrix = glm::mat4(1.0f); - - // Copy the current matrices to the current frame's uniform buffer - // Note: Since we requested a host coherent memory type for the uniform buffer, the write is instantly visible to the GPU - memcpy(uniformBuffers[currentFrame].mapped, &shaderData, sizeof(ShaderData)); - - // Build the command buffer - // Unlike in OpenGL all rendering commands are recorded into command buffers that are then submitted to the queue - // This allows to generate work upfront in a separate thread - // For basic command buffers (like in this sample), recording is so fast that there is no need to offload this - - vkResetCommandBuffer(commandBuffers[currentFrame], 0); - - VkCommandBufferBeginInfo cmdBufInfo{}; - cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - - // Set clear values for all framebuffer attachments with loadOp set to clear - // We use two attachments (color and depth) that are cleared at the start of the subpass and as such we need to set clear values for both - VkClearValue clearValues[2]{}; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo{}; - renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassBeginInfo.pNext = nullptr; - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - renderPassBeginInfo.framebuffer = frameBuffers[imageIndex]; - - const VkCommandBuffer commandBuffer = commandBuffers[currentFrame]; - VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &cmdBufInfo)); - - // Start the first sub pass specified in our default render pass setup by the base class - // This will clear the color and depth attachment - vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - // Update dynamic viewport state - VkViewport viewport{}; - viewport.height = (float)height; - viewport.width = (float)width; - viewport.minDepth = (float)0.0f; - viewport.maxDepth = (float)1.0f; - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - // Update dynamic scissor state - VkRect2D scissor{}; - scissor.extent.width = width; - scissor.extent.height = height; - scissor.offset.x = 0; - scissor.offset.y = 0; - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - // Bind descriptor set for the current frame's uniform buffer, so the shader uses the data from that buffer for this draw - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &uniformBuffers[currentFrame].descriptorSet, 0, nullptr); - // Bind the rendering pipeline - // The pipeline (state object) contains all states of the rendering pipeline, binding it will set all the states specified at pipeline creation time - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - // Bind triangle vertex buffer (contains position and colors) - VkDeviceSize offsets[1]{ 0 }; - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertices.buffer, offsets); - // Bind triangle index buffer - vkCmdBindIndexBuffer(commandBuffer, indices.buffer, 0, VK_INDEX_TYPE_UINT32); - // Draw indexed triangle - vkCmdDrawIndexed(commandBuffer, indices.count, 1, 0, 0, 0); - vkCmdEndRenderPass(commandBuffer); - // Ending the render pass will add an implicit barrier transitioning the frame buffer color attachment to - // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR for presenting it to the windowing system - VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer)); - - // Submit the command buffer to the graphics queue - - // Pipeline stage at which the queue submission will wait (via pWaitSemaphores) - VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - // The submit info structure specifies a command buffer queue submission batch - VkSubmitInfo submitInfo{}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at - submitInfo.pCommandBuffers = &commandBuffer; // Command buffers(s) to execute in this batch (submission) - submitInfo.commandBufferCount = 1; // We submit a single command buffer - - // Semaphore to wait upon before the submitted command buffer starts executing - submitInfo.pWaitSemaphores = &presentCompleteSemaphores[currentFrame]; - submitInfo.waitSemaphoreCount = 1; - // Semaphore to be signaled when command buffers have completed - submitInfo.pSignalSemaphores = &renderCompleteSemaphores[imageIndex]; - submitInfo.signalSemaphoreCount = 1; - - // Submit to the graphics queue passing a wait fence - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, waitFences[currentFrame])); - - // Present the current frame buffer to the swap chain - // Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation - // This ensures that the image is not presented to the windowing system until all commands have been submitted - - VkPresentInfoKHR presentInfo{}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = &renderCompleteSemaphores[imageIndex]; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = &swapChain.swapChain; - presentInfo.pImageIndices = &imageIndex; - result = vkQueuePresentKHR(queue, &presentInfo); - - if ((result == VK_ERROR_OUT_OF_DATE_KHR) || (result == VK_SUBOPTIMAL_KHR)) { - windowResize(); - } - else if (result != VK_SUCCESS) { - throw "Could not present the image to the swap chain!"; - } - - // Select the next frame to render to, based on the max. no. of concurrent frames - currentFrame = (currentFrame + 1) % MAX_CONCURRENT_FRAMES; - } -}; - -// OS specific main entry points -// Most of the code base is shared for the different supported operating systems, but stuff like message handling differs - -#if defined(_WIN32) -// Windows entry point -VulkanExample *vulkanExample; -LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (vulkanExample != NULL) - { - vulkanExample->handleMessages(hWnd, uMsg, wParam, lParam); - } - return (DefWindowProc(hWnd, uMsg, wParam, lParam)); -} -int APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR, _In_ int) -{ - for (size_t i = 0; i < __argc; i++) { VulkanExample::args.push_back(__argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->setupWindow(hInstance, WndProc); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - return 0; -} - -#elif defined(__ANDROID__) -// Android entry point -VulkanExample *vulkanExample; -void android_main(android_app* state) -{ - vulkanExample = new VulkanExample(); - state->userData = vulkanExample; - state->onAppCmd = VulkanExample::handleAppCommand; - state->onInputEvent = VulkanExample::handleAppInput; - androidApp = state; - vulkanExample->renderLoop(); - delete(vulkanExample); -} -#elif defined(_DIRECT2DISPLAY) - -// Linux entry point with direct to display wsi -// Direct to Displays (D2D) is used on embedded platforms -VulkanExample *vulkanExample; -static void handleEvent() -{ -} -int main(const int argc, const char *argv[]) -{ - for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - return 0; -} -#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT) -VulkanExample *vulkanExample; -static void handleEvent(const DFBWindowEvent *event) -{ - if (vulkanExample != NULL) - { - vulkanExample->handleEvent(event); - } -} -int main(const int argc, const char *argv[]) -{ - for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->setupWindow(); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - return 0; -} -#elif defined(VK_USE_PLATFORM_WAYLAND_KHR) -VulkanExample *vulkanExample; -int main(const int argc, const char *argv[]) -{ - for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->setupWindow(); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - return 0; -} -#elif defined(__linux__) || defined(__FreeBSD__) - -// Linux entry point -VulkanExample *vulkanExample; -#if defined(VK_USE_PLATFORM_XCB_KHR) -static void handleEvent(const xcb_generic_event_t *event) -{ - if (vulkanExample != NULL) - { - vulkanExample->handleEvent(event); - } -} -#else -static void handleEvent() -{ -} -#endif -int main(const int argc, const char *argv[]) -{ - for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->setupWindow(); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - return 0; -} -#elif (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_EXAMPLE_XCODE_GENERATED) -VulkanExample *vulkanExample; -int main(const int argc, const char *argv[]) -{ - @autoreleasepool - { - for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->setupWindow(nullptr); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - } - return 0; -} -#elif defined(VK_USE_PLATFORM_SCREEN_QNX) -VULKAN_EXAMPLE_MAIN() -#endif diff --git a/examples/trianglevulkan13/trianglevulkan13.cpp b/examples/trianglevulkan13/trianglevulkan13.cpp deleted file mode 100644 index 542d608a..00000000 --- a/examples/trianglevulkan13/trianglevulkan13.cpp +++ /dev/null @@ -1,963 +0,0 @@ -/* -* Vulkan Example - Basic indexed triangle rendering using Vulkan 1.3 -* -* Note: -* This is a variation of the the triangle sample that makes use of Vulkan 1.3 features -* This simplifies the api a bit, esp. with dynamic rendering replacing render passes (and with that framebuffers) -* -* Copyright (C) 2024-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include -#include -#include -#include -#include -#include -#include - -#define GLM_FORCE_RADIANS -#define GLM_FORCE_DEPTH_ZERO_TO_ONE -#include -#include - -#include -#include "vulkanexamplebase.h" - -// We want to keep GPU and CPU busy. To do that we may start building a new command buffer while the previous one is still being executed -// This number defines how many frames may be worked on simultaneously at once -// Increasing this number may improve performance but will also introduce additional latency -#define MAX_CONCURRENT_FRAMES 2 - -class VulkanExample : public VulkanExampleBase -{ -public: - // Vertex layout used in this example - struct Vertex { - float position[3]; - float color[3]; - }; - - struct VulkanBuffer { - VkDeviceMemory memory{ VK_NULL_HANDLE }; - VkBuffer handle{ VK_NULL_HANDLE }; - }; - - VulkanBuffer vertexBuffer; - VulkanBuffer indexBuffer; - uint32_t indexCount{ 0 }; - - // Uniform buffer block object - struct UniformBuffer : VulkanBuffer { - // The descriptor set stores the resources bound to the binding points in a shader - // It connects the binding points of the different shaders with the buffers and images used for those bindings - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - // We keep a pointer to the mapped buffer, so we can easily update it's contents via a memcpy - uint8_t* mapped{ nullptr }; - }; - // We use one UBO per frame, so we can have a frame overlap and make sure that uniforms aren't updated while still in use - std::array uniformBuffers; - - // For simplicity we use the same uniform block layout as in the shader - // This way we can just memcpy the data to the ubo - // Note: You should use data types that align with the GPU in order to avoid manual padding (vec4, mat4) - struct ShaderData { - glm::mat4 projectionMatrix; - glm::mat4 modelMatrix; - glm::mat4 viewMatrix; - }; - - // The pipeline layout is used by a pipeline to access the descriptor sets - // It defines interface (without binding any actual data) between the shader stages used by the pipeline and the shader resources - // A pipeline layout can be shared among multiple pipelines as long as their interfaces match - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - - // Pipelines (often called "pipeline state objects") are used to bake all states that affect a pipeline - // While in OpenGL every state can be changed at (almost) any time, Vulkan requires to layout the graphics (and compute) pipeline states upfront - // So for each combination of non-dynamic pipeline states you need a new pipeline (there are a few exceptions to this not discussed here) - // Even though this adds a new dimension of planning ahead, it's a great opportunity for performance optimizations by the driver - VkPipeline pipeline{ VK_NULL_HANDLE }; - - // The descriptor set layout describes the shader binding layout (without actually referencing descriptor) - // Like the pipeline layout it's pretty much a blueprint and can be used with different descriptor sets as long as their layout matches - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - // Synchronization primitives - // Synchronization is an important concept of Vulkan that OpenGL mostly hid away. Getting this right is crucial to using Vulkan. - // Semaphores are used to coordinate operations within the graphics queue and ensure correct command ordering - std::vector presentCompleteSemaphores{}; - std::vector renderCompleteSemaphores{}; - // Fences are used to make sure command buffers aren't rerecorded until they've finished executing - std::array waitFences{}; - - VkCommandPool commandPool{ VK_NULL_HANDLE }; - std::array commandBuffers{}; - - // To select the correct sync and command objects, we need to keep track of the current frame - uint32_t currentFrame{ 0 }; - - VkPhysicalDeviceVulkan13Features enabledFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES }; - - VulkanExample() : VulkanExampleBase() - { - title = "Basic indexed triangle using Vulkan 1.3"; - // To keep things simple, we don't use the UI overlay from the framework - settings.overlay = false; - // Setup a default look-at camera - camera.type = Camera::CameraType::lookat; - camera.setPosition(glm::vec3(0.0f, 0.0f, -2.5f)); - camera.setRotation(glm::vec3(0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 1.0f, 256.0f); - // We want to use Vulkan 1.3 with the dynamic rendering and sync 2 features - apiVersion = VK_API_VERSION_1_3; - enabledFeatures.dynamicRendering = VK_TRUE; - enabledFeatures.synchronization2 = VK_TRUE; - deviceCreatepNextChain = &enabledFeatures; - } - - ~VulkanExample() override - { - // Clean up used Vulkan resources - // Note: Inherited destructor cleans up resources stored in base class - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyBuffer(device, vertexBuffer.handle, nullptr); - vkFreeMemory(device, vertexBuffer.memory, nullptr); - vkDestroyBuffer(device, indexBuffer.handle, nullptr); - vkFreeMemory(device, indexBuffer.memory, nullptr); - vkDestroyCommandPool(device, commandPool, nullptr); - for (size_t i = 0; i < presentCompleteSemaphores.size(); i++) { - vkDestroySemaphore(device, presentCompleteSemaphores[i], nullptr); - } - for (size_t i = 0; i < renderCompleteSemaphores.size(); i++) { - vkDestroySemaphore(device, renderCompleteSemaphores[i], nullptr); - } - for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) { - vkDestroyFence(device, waitFences[i], nullptr); - vkDestroyBuffer(device, uniformBuffers[i].handle, nullptr); - vkFreeMemory(device, uniformBuffers[i].memory, nullptr); - } - } - } - - virtual void getEnabledFeatures() override - { - // Vulkan 1.3 device support is required for this example - if (deviceProperties.apiVersion < VK_API_VERSION_1_3) { - vks::tools::exitFatal("Selected GPU does not support support Vulkan 1.3", VK_ERROR_INCOMPATIBLE_DRIVER); - } - } - - // This function is used to request a device memory type that supports all the property flags we request (e.g. device local, host visible) - // Upon success it will return the index of the memory type that fits our requested memory properties - // This is necessary as implementations can offer an arbitrary number of memory types with different memory properties - // You can check https://vulkan.gpuinfo.org/ for details on different memory configurations - uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) - { - // Iterate over all memory types available for the device used in this example - for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++) { - if ((typeBits & 1) == 1) { - if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { - return i; - } - } - typeBits >>= 1; - } - throw "Could not find a suitable memory type!"; - } - - // Create the per-frame (in flight) and per (swapchain image) Vulkan synchronization primitives used in this example - void createSynchronizationPrimitives() - { - // Fences are per frame in flight - for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) { - // Fence used to ensure that command buffer has completed exection before using it again - VkFenceCreateInfo fenceCI{ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; - // Create the fences in signaled state (so we don't wait on first render of each command buffer) - fenceCI.flags = VK_FENCE_CREATE_SIGNALED_BIT; - VK_CHECK_RESULT(vkCreateFence(device, &fenceCI, nullptr, &waitFences[i])); - } - // Semaphores are used for correct command ordering within a queue - // Used to ensure that image presentation is complete before starting to submit again - presentCompleteSemaphores.resize(MAX_CONCURRENT_FRAMES); - for (auto& semaphore : presentCompleteSemaphores) { - VkSemaphoreCreateInfo semaphoreCI{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &semaphore)); - } - // Render completion - // Semaphore used to ensure that all commands submitted have been finished before submitting the image to the queue - renderCompleteSemaphores.resize(swapChain.images.size()); - for (auto& semaphore : renderCompleteSemaphores) { - VkSemaphoreCreateInfo semaphoreCI{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &semaphore)); - } - } - - // Command buffers are used to record commands to and are submitted to a queue for execution ("rendering") - void createCommandBuffers() - { - // All command buffers are allocated from the same command pool - VkCommandPoolCreateInfo commandPoolCI{ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; - commandPoolCI.queueFamilyIndex = swapChain.queueNodeIndex; - commandPoolCI.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - VK_CHECK_RESULT(vkCreateCommandPool(device, &commandPoolCI, nullptr, &commandPool)); - // Allocate one command buffer per max. concurrent frame from above pool - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, MAX_CONCURRENT_FRAMES); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commandBuffers.data())); - } - - // Prepare vertex and index buffers for an indexed triangle - // Also uploads them to device local memory using staging and initializes vertex input and attribute binding to match the vertex shader - void createVertexBuffer() - { - // A note on memory management in Vulkan in general: - // This is a complex topic and while it's fine for an example application to small individual memory allocations that is not - // what should be done a real-world application, where you should allocate large chunks of memory at once instead. - - // Setup vertices - const std::vector vertices{ - { { 1.0f, 1.0f, 0.0f }, { 1.0f, 0.0f, 0.0f } }, - { { -1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } }, - { { 0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } } - }; - uint32_t vertexBufferSize = static_cast(vertices.size()) * sizeof(Vertex); - - // Setup indices - // We do this for demonstration purposes, a triangle doesn't require indices to be rendered (because of the 1:1 mapping), but more complex shapes usually make use of indices - std::vector indices{ 0, 1, 2 }; - indexCount = static_cast(indices.size()); - uint32_t indexBufferSize = indexCount * sizeof(uint32_t); - - VkMemoryAllocateInfo memAlloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - VkMemoryRequirements memReqs; - - // Static data like vertex and index buffer should be stored on the device memory for optimal (and fastest) access by the GPU - // - // To achieve this we use so-called "staging buffers" : - // - Create a buffer that's visible to the host (and can be mapped) - // - Copy the data to this buffer - // - Create another buffer that's local on the device (VRAM) with the same size - // - Copy the data from the host to the device using a command buffer - // - Delete the host visible (staging) buffer - // - Use the device local buffers for rendering - // - // Note: On unified memory architectures where host (CPU) and GPU share the same memory, staging is not necessary - // To keep this sample easy to follow, there is no check for that in place - - // Create the host visible staging buffer that we copy vertices and indices too, and from which we copy to the device - VulkanBuffer stagingBuffer; - VkBufferCreateInfo stagingBufferCI{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - stagingBufferCI.size = vertexBufferSize + indexBufferSize; - // Buffer is used as the copy source - stagingBufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - // Create a host-visible buffer to copy the vertex data to (staging buffer) - VK_CHECK_RESULT(vkCreateBuffer(device, &stagingBufferCI, nullptr, &stagingBuffer.handle)); - vkGetBufferMemoryRequirements(device, stagingBuffer.handle, &memReqs); - memAlloc.allocationSize = memReqs.size; - // Request a host visible memory type that can be used to copy our data to - // Also request it to be coherent, so that writes are visible to the GPU right after unmapping the buffer - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffer.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer.handle, stagingBuffer.memory, 0)); - // Map the buffer and copy vertices and indices into it, this way we can use a single buffer as the source for both vertex and index GPU buffers - uint8_t* data{ nullptr }; - VK_CHECK_RESULT(vkMapMemory(device, stagingBuffer.memory, 0, memAlloc.allocationSize, 0, (void**)&data)); - memcpy(data, vertices.data(), vertexBufferSize); - memcpy(((char*)data) + vertexBufferSize, indices.data(), indexBufferSize); - - // Create a device local buffer to which the (host local) vertex data will be copied and which will be used for rendering - VkBufferCreateInfo vertexbufferCI{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - vertexbufferCI.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - vertexbufferCI.size = vertexBufferSize; - VK_CHECK_RESULT(vkCreateBuffer(device, &vertexbufferCI, nullptr, &vertexBuffer.handle)); - vkGetBufferMemoryRequirements(device, vertexBuffer.handle, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &vertexBuffer.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, vertexBuffer.handle, vertexBuffer.memory, 0)); - - // Create a device local buffer to which the (host local) index data will be copied and which will be used for rendering - VkBufferCreateInfo indexbufferCI{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - indexbufferCI.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - indexbufferCI.size = indexBufferSize; - VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferCI, nullptr, &indexBuffer.handle)); - vkGetBufferMemoryRequirements(device, indexBuffer.handle, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &indexBuffer.memory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, indexBuffer.handle, indexBuffer.memory, 0)); - - // Buffer copies have to be submitted to a queue, so we need a command buffer for them - VkCommandBuffer copyCmd; - - VkCommandBufferAllocateInfo cmdBufAllocateInfo{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; - cmdBufAllocateInfo.commandPool = commandPool; - cmdBufAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cmdBufAllocateInfo.commandBufferCount = 1; - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, ©Cmd)); - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo)); - // Copy vertex and index buffers to the device - VkBufferCopy copyRegion{}; - copyRegion.size = vertexBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffer.handle, vertexBuffer.handle, 1, ©Region); - copyRegion.size = indexBufferSize; - // Indices are stored after the vertices in the source buffer, so we need to add an offset - copyRegion.srcOffset = vertexBufferSize; - vkCmdCopyBuffer(copyCmd, stagingBuffer.handle, indexBuffer.handle, 1, ©Region); - VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd)); - - // Submit the command buffer to the queue to finish the copy - VkSubmitInfo submitInfo{ VK_STRUCTURE_TYPE_SUBMIT_INFO }; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = ©Cmd; - - // Create fence to ensure that the command buffer has finished executing - VkFenceCreateInfo fenceCI{ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; - VkFence fence; - VK_CHECK_RESULT(vkCreateFence(device, &fenceCI, nullptr, &fence)); - // Submit copies to the queue - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence)); - // Wait for the fence to signal that command buffer has finished executing - VK_CHECK_RESULT(vkWaitForFences(device, 1, &fence, VK_TRUE, DEFAULT_FENCE_TIMEOUT)); - vkDestroyFence(device, fence, nullptr); - vkFreeCommandBuffers(device, commandPool, 1, ©Cmd); - - // The fence made sure copies are finished, so we can safely delete the staging buffer - vkDestroyBuffer(device, stagingBuffer.handle, nullptr); - vkFreeMemory(device, stagingBuffer.memory, nullptr); - } - - // Decriptors are used to pass data to shaders, for our sample we use a descriptor to pass parameters like matrices to the shader - void createDescriptors() - { - // Descriptors are allocated from a pool, that tells the implementation how many and what types of descriptors we are going to use (at maximum) - VkDescriptorPoolSize descriptorTypeCounts[1]{}; - // This example only one descriptor type (uniform buffer) - descriptorTypeCounts[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - // We have one buffer (and as such descriptor) per frame - descriptorTypeCounts[0].descriptorCount = MAX_CONCURRENT_FRAMES; - // For additional types you need to add new entries in the type count list - // E.g. for two combined image samplers : - // typeCounts[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - // typeCounts[1].descriptorCount = 2; - - // Create the global descriptor pool - // All descriptors used in this example are allocated from this pool - VkDescriptorPoolCreateInfo descriptorPoolCI{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; - descriptorPoolCI.poolSizeCount = 1; - descriptorPoolCI.pPoolSizes = descriptorTypeCounts; - // Set the max. number of descriptor sets that can be requested from this pool (requesting beyond this limit will result in an error) - // Our sample will create one set per uniform buffer per frame - descriptorPoolCI.maxSets = MAX_CONCURRENT_FRAMES; - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorPool)); - - // Descriptor set layouts define the interface between our application and the shader - // Basically connects the different shader stages to descriptors for binding uniform buffers, image samplers, etc. - // So every shader binding should map to one descriptor set layout binding - // Binding 0: Uniform buffer (Vertex shader) - VkDescriptorSetLayoutBinding layoutBinding{}; - layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - layoutBinding.descriptorCount = 1; - layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; - descriptorLayoutCI.bindingCount = 1; - descriptorLayoutCI.pBindings = &layoutBinding; - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayout)); - - // Where the descriptor set layout is the interface, the descriptor set points to actual data - // Descriptors that are changed per frame need to be multiplied, so we can update descriptor n+1 while n is still used by the GPU, so we create one per max frame in flight - for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) { - VkDescriptorSetAllocateInfo allocInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; - allocInfo.descriptorPool = descriptorPool; - allocInfo.descriptorSetCount = 1; - allocInfo.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &uniformBuffers[i].descriptorSet)); - - // Update the descriptor set determining the shader binding points - // For every binding point used in a shader there needs to be one - // descriptor set matching that binding point - VkWriteDescriptorSet writeDescriptorSet{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; - - // The buffer's information is passed using a descriptor info structure - VkDescriptorBufferInfo bufferInfo{}; - bufferInfo.buffer = uniformBuffers[i].handle; - bufferInfo.range = sizeof(ShaderData); - - // Binding 0 : Uniform buffer - writeDescriptorSet.dstSet = uniformBuffers[i].descriptorSet; - writeDescriptorSet.descriptorCount = 1; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - writeDescriptorSet.pBufferInfo = &bufferInfo; - writeDescriptorSet.dstBinding = 0; - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - } - - // Create the depth (and stencil) buffer attachments - // While we don't do any depth testing in this sample, having depth testing is very common so it's a good idea to learn it from the very start - void setupDepthStencil() override - { - // Create an optimal tiled image used as the depth stencil attachment - VkImageCreateInfo imageCI{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = depthFormat; - imageCI.extent = { width, height, 1 }; - imageCI.mipLevels = 1; - imageCI.arrayLayers = 1; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &depthStencil.image)); - - // Allocate memory for the image (device local) and bind it to our image - VkMemoryAllocateInfo memAlloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, depthStencil.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depthStencil.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, depthStencil.image, depthStencil.memory, 0)); - - // Create a view for the depth stencil image - // Images aren't directly accessed in Vulkan, but rather through views described by a subresource range - // This allows for multiple views of one image with differing ranges (e.g. for different layers) - VkImageViewCreateInfo depthStencilViewCI{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - depthStencilViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilViewCI.format = depthFormat; - depthStencilViewCI.subresourceRange = {}; - depthStencilViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - // Stencil aspect should only be set on depth + stencil formats (VK_FORMAT_D16_UNORM_S8_UINT..VK_FORMAT_D32_SFLOAT_S8_UINT) - if (depthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) { - depthStencilViewCI.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - depthStencilViewCI.subresourceRange.baseMipLevel = 0; - depthStencilViewCI.subresourceRange.levelCount = 1; - depthStencilViewCI.subresourceRange.baseArrayLayer = 0; - depthStencilViewCI.subresourceRange.layerCount = 1; - depthStencilViewCI.image = depthStencil.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilViewCI, nullptr, &depthStencil.view)); - } - - // Vulkan loads its shaders from an immediate binary representation called SPIR-V - // Shaders are compiled offline from e.g. GLSL using the reference glslang compiler - // This function loads such a shader from a binary file and returns a shader module structure - VkShaderModule loadSPIRVShader(const std::string& filename) - { - size_t shaderSize; - char* shaderCode{ nullptr }; - -#if defined(__ANDROID__) - // Load shader from compressed asset - AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); - assert(asset); - shaderSize = AAsset_getLength(asset); - assert(shaderSize > 0); - - shaderCode = new char[shaderSize]; - AAsset_read(asset, shaderCode, shaderSize); - AAsset_close(asset); -#else - std::ifstream is(filename, std::ios::binary | std::ios::in | std::ios::ate); - - if (is.is_open()) { - shaderSize = is.tellg(); - is.seekg(0, std::ios::beg); - // Copy file contents into a buffer - shaderCode = new char[shaderSize]; - is.read(shaderCode, shaderSize); - is.close(); - assert(shaderSize > 0); - } -#endif - if (shaderCode) { - // Create a new shader module that will be used for pipeline creation - VkShaderModuleCreateInfo shaderModuleCI{ VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO }; - shaderModuleCI.codeSize = shaderSize; - shaderModuleCI.pCode = (uint32_t*)shaderCode; - - VkShaderModule shaderModule; - VK_CHECK_RESULT(vkCreateShaderModule(device, &shaderModuleCI, nullptr, &shaderModule)); - - delete[] shaderCode; - - return shaderModule; - } else { - std::cerr << "Error: Could not open shader file \"" << filename << "\"" << std::endl; - return VK_NULL_HANDLE; - } - } - - void createPipeline() - { - // The pipeline layout is the interface telling the pipeline what type of descriptors will later be bound - VkPipelineLayoutCreateInfo pipelineLayoutCI{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; - pipelineLayoutCI.setLayoutCount = 1; - pipelineLayoutCI.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Create the graphics pipeline used in this example - // Vulkan uses the concept of rendering pipelines to encapsulate fixed states, replacing OpenGL's complex state machine - // A pipeline is then stored and hashed on the GPU making pipeline changes very fast - - VkGraphicsPipelineCreateInfo pipelineCI{ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; - // The layout used for this pipeline (can be shared among multiple pipelines using the same layout) - pipelineCI.layout = pipelineLayout; - - // Construct the different states making up the pipeline - - // Input assembly state describes how primitives are assembled - // This pipeline will assemble vertex data as a triangle lists (though we only use one triangle) - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI{ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; - inputAssemblyStateCI.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - - // Rasterization state - VkPipelineRasterizationStateCreateInfo rasterizationStateCI{ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; - rasterizationStateCI.polygonMode = VK_POLYGON_MODE_FILL; - rasterizationStateCI.cullMode = VK_CULL_MODE_NONE; - rasterizationStateCI.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterizationStateCI.depthClampEnable = VK_FALSE; - rasterizationStateCI.rasterizerDiscardEnable = VK_FALSE; - rasterizationStateCI.depthBiasEnable = VK_FALSE; - rasterizationStateCI.lineWidth = 1.0f; - - // Color blend state describes how blend factors are calculated (if used) - // We need one blend attachment state per color attachment (even if blending is not used) - VkPipelineColorBlendAttachmentState blendAttachmentState{}; - blendAttachmentState.colorWriteMask = 0xf; - blendAttachmentState.blendEnable = VK_FALSE; - VkPipelineColorBlendStateCreateInfo colorBlendStateCI{ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; - colorBlendStateCI.attachmentCount = 1; - colorBlendStateCI.pAttachments = &blendAttachmentState; - - // Viewport state sets the number of viewports and scissor used in this pipeline - // Note: This is actually overridden by the dynamic states (see below) - VkPipelineViewportStateCreateInfo viewportStateCI{ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO }; - viewportStateCI.viewportCount = 1; - viewportStateCI.scissorCount = 1; - - // Enable dynamic states - // Most states are baked into the pipeline, but there is somee state that can be dynamically changed within the command buffer to mak e things easuer - // To be able to change these we need do specify which dynamic states will be changed using this pipeline. Their actual states are set later on in the command buffer - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI{ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; - dynamicStateCI.pDynamicStates = dynamicStateEnables.data(); - dynamicStateCI.dynamicStateCount = static_cast(dynamicStateEnables.size()); - - // Depth and stencil state containing depth and stencil compare and test operations - // We only use depth tests and want depth tests and writes to be enabled and compare with less or equal - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI{ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO }; - depthStencilStateCI.depthTestEnable = VK_TRUE; - depthStencilStateCI.depthWriteEnable = VK_TRUE; - depthStencilStateCI.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; - depthStencilStateCI.depthBoundsTestEnable = VK_FALSE; - depthStencilStateCI.back.failOp = VK_STENCIL_OP_KEEP; - depthStencilStateCI.back.passOp = VK_STENCIL_OP_KEEP; - depthStencilStateCI.back.compareOp = VK_COMPARE_OP_ALWAYS; - depthStencilStateCI.stencilTestEnable = VK_FALSE; - depthStencilStateCI.front = depthStencilStateCI.back; - - // This example does not make use of multi sampling (for anti-aliasing), the state must still be set and passed to the pipeline - VkPipelineMultisampleStateCreateInfo multisampleStateCI{ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; - multisampleStateCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - // Vertex input descriptions - // Specifies the vertex input parameters for a pipeline - - // Vertex input binding - // This example uses a single vertex input binding at binding point 0 (see vkCmdBindVertexBuffers) - VkVertexInputBindingDescription vertexInputBinding{}; - vertexInputBinding.binding = 0; - vertexInputBinding.stride = sizeof(Vertex); - vertexInputBinding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - // Input attribute bindings describe shader attribute locations and memory layouts - std::array vertexInputAttributs{}; - // These match the following shader layout (see triangle.vert): - // layout (location = 0) in vec3 inPos; - // layout (location = 1) in vec3 inColor; - // Attribute location 0: Position - vertexInputAttributs[0].binding = 0; - vertexInputAttributs[0].location = 0; - // Position attribute is three 32 bit signed (SFLOAT) floats (R32 G32 B32) - vertexInputAttributs[0].format = VK_FORMAT_R32G32B32_SFLOAT; - vertexInputAttributs[0].offset = offsetof(Vertex, position); - // Attribute location 1: Color - vertexInputAttributs[1].binding = 0; - vertexInputAttributs[1].location = 1; - // Color attribute is three 32 bit signed (SFLOAT) floats (R32 G32 B32) - vertexInputAttributs[1].format = VK_FORMAT_R32G32B32_SFLOAT; - vertexInputAttributs[1].offset = offsetof(Vertex, color); - - // Vertex input state used for pipeline creation - VkPipelineVertexInputStateCreateInfo vertexInputStateCI{ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; - vertexInputStateCI.vertexBindingDescriptionCount = 1; - vertexInputStateCI.pVertexBindingDescriptions = &vertexInputBinding; - vertexInputStateCI.vertexAttributeDescriptionCount = 2; - vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributs.data(); - - // Shaders - std::array shaderStages{}; - - // Vertex shader - shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shaderStages[0].module = loadSPIRVShader(getShadersPath() + "triangle/triangle.vert.spv"); - shaderStages[0].pName = "main"; - assert(shaderStages[0].module != VK_NULL_HANDLE); - - // Fragment shader - shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderStages[1].module = loadSPIRVShader(getShadersPath() + "triangle/triangle.frag.spv"); - shaderStages[1].pName = "main"; - assert(shaderStages[1].module != VK_NULL_HANDLE); - - // Set pipeline shader stage info - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - // Attachment information for dynamic rendering - VkPipelineRenderingCreateInfoKHR pipelineRenderingCI{ VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR }; - pipelineRenderingCI.colorAttachmentCount = 1; - pipelineRenderingCI.pColorAttachmentFormats = &swapChain.colorFormat; - pipelineRenderingCI.depthAttachmentFormat = depthFormat; - pipelineRenderingCI.stencilAttachmentFormat = depthFormat; - - // Assign the pipeline states to the pipeline creation info structure - pipelineCI.pVertexInputState = &vertexInputStateCI; - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.pNext = &pipelineRenderingCI; - - // Create rendering pipeline using the specified states - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - - // Shader modules can safely be destroyed when the pipeline has been created - vkDestroyShaderModule(device, shaderStages[0].module, nullptr); - vkDestroyShaderModule(device, shaderStages[1].module, nullptr); - } - - void createUniformBuffers() - { - // Prepare and initialize the per-frame uniform buffer blocks containing shader uniforms - // Single uniforms like in OpenGL are no longer present in Vulkan. All shader uniforms are passed via uniform buffer blocks - VkBufferCreateInfo bufferInfo{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - bufferInfo.size = sizeof(ShaderData); - // This buffer will be used as a uniform buffer - bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - - // Create the buffers - for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) { - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferInfo, nullptr, &uniformBuffers[i].handle)); - // Get memory requirements including size, alignment and memory type based on the buffer type we request (uniform buffer) - VkMemoryRequirements memReqs; - vkGetBufferMemoryRequirements(device, uniformBuffers[i].handle, &memReqs); - VkMemoryAllocateInfo allocInfo{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - // Note that we use the size we got from the memory requirements and not the actual buffer size, as the former may be larger due to alignment requirements of the device - allocInfo.allocationSize = memReqs.size; - // Get the memory type index that supports host visible memory access - // Most implementations offer multiple memory types and selecting the correct one to allocate memory from is crucial - // We also want the buffer to be host coherent so we don't have to flush (or sync after every update). - allocInfo.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - // Allocate memory for the uniform buffer - VK_CHECK_RESULT(vkAllocateMemory(device, &allocInfo, nullptr, &(uniformBuffers[i].memory))); - // Bind memory to buffer - VK_CHECK_RESULT(vkBindBufferMemory(device, uniformBuffers[i].handle, uniformBuffers[i].memory, 0)); - // We map the buffer once, so we can update it without having to map it again - VK_CHECK_RESULT(vkMapMemory(device, uniformBuffers[i].memory, 0, sizeof(ShaderData), 0, (void**)&uniformBuffers[i].mapped)); - } - - } - - void prepare() override - { - VulkanExampleBase::prepare(); - createSynchronizationPrimitives(); - createCommandBuffers(); - createVertexBuffer(); - createUniformBuffers(); - createDescriptors(); - createPipeline(); - prepared = true; - } - - void render() override - { - // Use a fence to wait until the command buffer has finished execution before using it again - vkWaitForFences(device, 1, &waitFences[currentFrame], VK_TRUE, UINT64_MAX); - VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[currentFrame])); - - // Get the next swap chain image from the implementation - // Note that the implementation is free to return the images in any order, so we must use the acquire function and can't just cycle through the images/imageIndex on our own - uint32_t imageIndex{ 0 }; - VkResult result = vkAcquireNextImageKHR(device, swapChain.swapChain, UINT64_MAX, presentCompleteSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); - if (result == VK_ERROR_OUT_OF_DATE_KHR) { - windowResize(); - return; - } else if ((result != VK_SUCCESS) && (result != VK_SUBOPTIMAL_KHR)) { - throw "Could not acquire the next swap chain image!"; - } - - // Update the uniform buffer for the next frame - ShaderData shaderData{}; - shaderData.projectionMatrix = camera.matrices.perspective; - shaderData.viewMatrix = camera.matrices.view; - shaderData.modelMatrix = glm::mat4(1.0f); - // Copy the current matrices to the current frame's uniform buffer. As we requested a host coherent memory type for the uniform buffer, the write is instantly visible to the GPU. - memcpy(uniformBuffers[currentFrame].mapped, &shaderData, sizeof(ShaderData)); - - // Build the command buffer for the next frame to render - vkResetCommandBuffer(commandBuffers[currentFrame], 0); - VkCommandBufferBeginInfo cmdBufInfo{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - const VkCommandBuffer commandBuffer = commandBuffers[currentFrame]; - VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &cmdBufInfo)); - - // With dynamic rendering we need to explicitly add layout transitions by using barriers, this set of barriers prepares the color and depth images for output - vks::tools::insertImageMemoryBarrier(commandBuffer, swapChain.images[imageIndex], 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - vks::tools::insertImageMemoryBarrier(commandBuffer, depthStencil.image, 0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VkImageSubresourceRange{ VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1 }); - - // New structures are used to define the attachments used in dynamic rendering - // Color attachment - VkRenderingAttachmentInfo colorAttachment{ VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO }; - colorAttachment.imageView = swapChain.imageViews[imageIndex]; - colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.clearValue.color = { 0.0f, 0.0f, 0.2f, 0.0f }; - // Depth/stencil attachment - VkRenderingAttachmentInfo depthStencilAttachment{ VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO }; - depthStencilAttachment.imageView = depthStencil.view; - depthStencilAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - depthStencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - depthStencilAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthStencilAttachment.clearValue.depthStencil = { 1.0f, 0 }; - - VkRenderingInfo renderingInfo{ VK_STRUCTURE_TYPE_RENDERING_INFO_KHR }; - renderingInfo.renderArea = { 0, 0, width, height }; - renderingInfo.layerCount = 1; - renderingInfo.colorAttachmentCount = 1; - renderingInfo.pColorAttachments = &colorAttachment; - renderingInfo.pDepthAttachment = &depthStencilAttachment; - renderingInfo.pStencilAttachment = &depthStencilAttachment; - - // Start a dynamic rendering section - vkCmdBeginRendering(commandBuffer, &renderingInfo); - // Update dynamic viewport state - VkViewport viewport{ 0.0f, 0.0f, (float)width, (float)height, 0.0f, 1.0f }; - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - // Update dynamic scissor state - VkRect2D scissor{ 0, 0, width, height }; - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - // Bind descriptor set for the current frame's uniform buffer, so the shader uses the data from that buffer for this draw - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &uniformBuffers[currentFrame].descriptorSet, 0, nullptr); - // The pipeline (state object) contains all states of the rendering pipeline, binding it will set all the states specified at pipeline creation time - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - // Bind triangle vertex buffer (contains position and colors) - VkDeviceSize offsets[1]{ 0 }; - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer.handle, offsets); - // Bind triangle index buffer - vkCmdBindIndexBuffer(commandBuffer, indexBuffer.handle, 0, VK_INDEX_TYPE_UINT32); - // Draw indexed triangle - vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0); - // Finish the current dynamic rendering section - vkCmdEndRendering(commandBuffer); - - // This barrier prepares the color image for presentation, we don't need to care for the depth image - vks::tools::insertImageMemoryBarrier(commandBuffer, swapChain.images[imageIndex], VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_NONE, VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); - VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer)); - - // Submit the command buffer to the graphics queue - - // Pipeline stage at which the queue submission will wait (via pWaitSemaphores) - VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - // The submit info structure specifies a command buffer queue submission batch - VkSubmitInfo submitInfo{ VK_STRUCTURE_TYPE_SUBMIT_INFO }; - submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at - submitInfo.pCommandBuffers = &commandBuffer; // Command buffers(s) to execute in this batch (submission) - submitInfo.commandBufferCount = 1; // We submit a single command buffer - - // Semaphore to wait upon before the submitted command buffer starts executing - submitInfo.pWaitSemaphores = &presentCompleteSemaphores[currentFrame]; - submitInfo.waitSemaphoreCount = 1; - // Semaphore to be signaled when command buffers have completed - submitInfo.pSignalSemaphores = &renderCompleteSemaphores[imageIndex]; - submitInfo.signalSemaphoreCount = 1; - - // Submit to the graphics queue passing a wait fence - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, waitFences[currentFrame])); - - // Present the current frame buffer to the swap chain - // Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation - // This ensures that the image is not presented to the windowing system until all commands have been submitted - VkPresentInfoKHR presentInfo{ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = &renderCompleteSemaphores[imageIndex]; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = &swapChain.swapChain; - presentInfo.pImageIndices = &imageIndex; - result = vkQueuePresentKHR(queue, &presentInfo); - if ((result == VK_ERROR_OUT_OF_DATE_KHR) || (result == VK_SUBOPTIMAL_KHR)) { - windowResize(); - } else if (result != VK_SUCCESS) { - throw "Could not present the image to the swap chain!"; - } - - // Select the next frame to render to, based on the max. no. of concurrent frames - currentFrame = (currentFrame + 1) % MAX_CONCURRENT_FRAMES; - } - - // Override these as otherwise the base class would generate frame buffers and render passes - void setupFrameBuffer() override {} - void setupRenderPass() override {} -}; - -// OS specific main entry points -// Most of the code base is shared for the different supported operating systems, but stuff like message handling differs - -#if defined(_WIN32) -// Windows entry point -VulkanExample *vulkanExample; -LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (vulkanExample != NULL) - { - vulkanExample->handleMessages(hWnd, uMsg, wParam, lParam); - } - return (DefWindowProc(hWnd, uMsg, wParam, lParam)); -} -int APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR, _In_ int) -{ - for (size_t i = 0; i < __argc; i++) { VulkanExample::args.push_back(__argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->setupWindow(hInstance, WndProc); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - return 0; -} - -#elif defined(__ANDROID__) -// Android entry point -VulkanExample *vulkanExample; -void android_main(android_app* state) -{ - vulkanExample = new VulkanExample(); - state->userData = vulkanExample; - state->onAppCmd = VulkanExample::handleAppCommand; - state->onInputEvent = VulkanExample::handleAppInput; - androidApp = state; - vulkanExample->renderLoop(); - delete(vulkanExample); -} -#elif defined(_DIRECT2DISPLAY) - -// Linux entry point with direct to display wsi -// Direct to Displays (D2D) is used on embedded platforms -VulkanExample *vulkanExample; -static void handleEvent() -{ -} -int main(const int argc, const char *argv[]) -{ - for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - return 0; -} -#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT) -VulkanExample *vulkanExample; -static void handleEvent(const DFBWindowEvent *event) -{ - if (vulkanExample != NULL) - { - vulkanExample->handleEvent(event); - } -} -int main(const int argc, const char *argv[]) -{ - for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->setupWindow(); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - return 0; -} -#elif defined(VK_USE_PLATFORM_WAYLAND_KHR) -VulkanExample *vulkanExample; -int main(const int argc, const char *argv[]) -{ - for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->setupWindow(); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - return 0; -} -#elif defined(__linux__) || defined(__FreeBSD__) - -// Linux entry point -VulkanExample *vulkanExample; -#if defined(VK_USE_PLATFORM_XCB_KHR) -static void handleEvent(const xcb_generic_event_t *event) -{ - if (vulkanExample != NULL) - { - vulkanExample->handleEvent(event); - } -} -#else -static void handleEvent() -{ -} -#endif -int main(const int argc, const char *argv[]) -{ - for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->setupWindow(); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - return 0; -} -#elif (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_EXAMPLE_XCODE_GENERATED) -VulkanExample *vulkanExample; -int main(const int argc, const char *argv[]) -{ - @autoreleasepool - { - for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; - vulkanExample = new VulkanExample(); - vulkanExample->initVulkan(); - vulkanExample->setupWindow(nullptr); - vulkanExample->prepare(); - vulkanExample->renderLoop(); - delete(vulkanExample); - } - return 0; -} -#elif defined(VK_USE_PLATFORM_SCREEN_QNX) -VULKAN_EXAMPLE_MAIN() -#endif diff --git a/examples/validate_all.py b/examples/validate_all.py deleted file mode 100644 index aaf3daa7..00000000 --- a/examples/validate_all.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2025 by Sascha Willems - www.saschawillems.de -# This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - -# Runs all samples in benchmark mode and stores all validation messages into a single text file - -# Note: Needs to be copied to where the binary files have been compiled (e.g. build/windows/bin/debug) - -import glob -import subprocess -import os -import platform - -if os.path.exists("validation_output.txt"): - os.remove("validation_output.txt") -if platform.system() == 'Linux' or platform.system() == 'Darwin': - binaries = "./*" -else: - binaries = "*.exe" -for sample in glob.glob(binaries): - # Skip headless samples, as they require a manual keypress - if "headless" in sample: - continue - subprocess.call("%s -v -vl -b -bfs %s" % (sample, 50), shell=True) \ No newline at end of file diff --git a/examples/variablerateshading/variablerateshading.cpp b/examples/variablerateshading/variablerateshading.cpp deleted file mode 100644 index 6c07987c..00000000 --- a/examples/variablerateshading/variablerateshading.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* -* Vulkan Example - Variable rate shading -* -* Copyright (C) 2020-2024 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "variablerateshading.h" - -VulkanExample::VulkanExample() : VulkanExampleBase() -{ - title = "Variable rate shading"; - apiVersion = VK_API_VERSION_1_1; - camera.type = Camera::CameraType::firstperson; - camera.flipY = true; - camera.setPosition(glm::vec3(0.0f, 1.0f, 0.0f)); - camera.setRotation(glm::vec3(0.0f, -90.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - camera.setRotationSpeed(0.25f); - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME); -} - -VulkanExample::~VulkanExample() -{ - vkDestroyPipeline(device, pipelines.masked, nullptr); - vkDestroyPipeline(device, pipelines.opaque, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyImageView(device, shadingRateImage.view, nullptr); - vkDestroyImage(device, shadingRateImage.image, nullptr); - vkFreeMemory(device, shadingRateImage.memory, nullptr); - shaderData.buffer.destroy(); -} - -void VulkanExample::getEnabledFeatures() -{ - enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy; - // POI - enabledPhysicalDeviceShadingRateImageFeaturesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR; - enabledPhysicalDeviceShadingRateImageFeaturesKHR.attachmentFragmentShadingRate = VK_TRUE; - enabledPhysicalDeviceShadingRateImageFeaturesKHR.pipelineFragmentShadingRate = VK_FALSE; - enabledPhysicalDeviceShadingRateImageFeaturesKHR.primitiveFragmentShadingRate = VK_FALSE; - deviceCreatepNextChain = &enabledPhysicalDeviceShadingRateImageFeaturesKHR; -} - -/* - If the window has been resized, we need to recreate the shading rate image and the render pass. That's because the render pass holds information on the fragment shading rate image resolution - -*/ -void VulkanExample::handleResize() -{ - vkDeviceWaitIdle(device); - // Invalidate the shading rate image, will be recreated in the renderpass setup - vkDestroyImageView(device, shadingRateImage.view, nullptr); - vkDestroyImage(device, shadingRateImage.image, nullptr); - vkFreeMemory(device, shadingRateImage.memory, nullptr); - prepareShadingRateImage(); - // Recreate the render pass and update it with the new fragment shading rate image resolution - vkDestroyRenderPass(device, renderPass, nullptr); - setupRenderPass(); - resized = false; -} - -void VulkanExample::setupFrameBuffer() -{ - if (resized) { - handleResize(); - } - - if (shadingRateImage.image == VK_NULL_HANDLE) { - prepareShadingRateImage(); - } - - VkImageView attachments[3]; - - // Depth/Stencil attachment is the same for all frame buffers - attachments[1] = depthStencil.view; - // Fragment shading rate attachment - attachments[2] = shadingRateImage.view; - - VkFramebufferCreateInfo frameBufferCreateInfo{}; - frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - frameBufferCreateInfo.renderPass = renderPass; - frameBufferCreateInfo.attachmentCount = 3; - frameBufferCreateInfo.pAttachments = attachments; - frameBufferCreateInfo.width = width; - frameBufferCreateInfo.height = height; - frameBufferCreateInfo.layers = 1; - - // Create frame buffers for every swap chain image - frameBuffers.resize(swapChain.images.size()); - for (uint32_t i = 0; i < frameBuffers.size(); i++) { - attachments[0] = swapChain.imageViews[i]; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCreateInfo, nullptr, &frameBuffers[i])); - } -} - -void VulkanExample::setupRenderPass() -{ - // Note that we need to use ...2KHR types in here, as fragment shading rate requires additional properties and structs to be passed at renderpass creation - if (!vkCreateRenderPass2KHR) { - vkCreateRenderPass2KHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateRenderPass2KHR")); - } - - if (shadingRateImage.image == VK_NULL_HANDLE) { - prepareShadingRateImage(); - } - - std::array attachments = {}; - // Color attachment - attachments[0].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; - attachments[0].format = swapChain.colorFormat; - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - // Depth attachment - attachments[1].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; - attachments[1].format = depthFormat; - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - // Fragment shading rate attachment - attachments[2].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; - attachments[2].format = VK_FORMAT_R8_UINT; - attachments[2].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[2].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachments[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[2].initialLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; - attachments[2].finalLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; - - VkAttachmentReference2KHR colorReference = {}; - colorReference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; - colorReference.attachment = 0; - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - colorReference.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - VkAttachmentReference2KHR depthReference = {}; - depthReference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; - depthReference.attachment = 1; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - depthReference.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - - // Setup the attachment reference for the shading rate image attachment in slot 2 - VkAttachmentReference2 fragmentShadingRateReference{}; - fragmentShadingRateReference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; - fragmentShadingRateReference.attachment = 2; - fragmentShadingRateReference.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; - - // Setup the attachment info for the shading rate image, which will be added to the sub pass via structure chaining (in pNext) - VkFragmentShadingRateAttachmentInfoKHR fragmentShadingRateAttachmentInfo{}; - fragmentShadingRateAttachmentInfo.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR; - fragmentShadingRateAttachmentInfo.pFragmentShadingRateAttachment = &fragmentShadingRateReference; - fragmentShadingRateAttachmentInfo.shadingRateAttachmentTexelSize.width = physicalDeviceShadingRateImageProperties.maxFragmentShadingRateAttachmentTexelSize.width; - fragmentShadingRateAttachmentInfo.shadingRateAttachmentTexelSize.height = physicalDeviceShadingRateImageProperties.maxFragmentShadingRateAttachmentTexelSize.height; - - VkSubpassDescription2KHR subpassDescription = {}; - subpassDescription.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; - subpassDescription.pColorAttachments = &colorReference; - subpassDescription.pDepthStencilAttachment = &depthReference; - subpassDescription.inputAttachmentCount = 0; - subpassDescription.pInputAttachments = nullptr; - subpassDescription.preserveAttachmentCount = 0; - subpassDescription.pPreserveAttachments = nullptr; - subpassDescription.pResolveAttachments = nullptr; - subpassDescription.pNext = &fragmentShadingRateAttachmentInfo; - - // Subpass dependencies for layout transitions - std::array dependencies = {}; - - dependencies[0].sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2; - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2; - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo2KHR renderPassCI = {}; - renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2; - renderPassCI.attachmentCount = static_cast(attachments.size()); - renderPassCI.pAttachments = attachments.data(); - renderPassCI.subpassCount = 1; - renderPassCI.pSubpasses = &subpassDescription; - renderPassCI.dependencyCount = static_cast(dependencies.size()); - renderPassCI.pDependencies = dependencies.data(); - - VK_CHECK_RESULT(vkCreateRenderPass2KHR(device, &renderPassCI, nullptr, &renderPass)); -} - -void VulkanExample::buildCommandBuffers() -{ - // As this is an extension, we need to manually load the extension pointers - if (!vkCmdSetFragmentShadingRateKHR) { - vkCmdSetFragmentShadingRateKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdSetFragmentShadingRateKHR")); - } - - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[3]; - clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };; - clearValues[1].depthStencil = { 1.0f, 0 }; - clearValues[2].color = { {0.0f, 0.0f, 0.0f, 0.0f} }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 3; - renderPassBeginInfo.pClearValues = clearValues; - - const VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - const VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - // Set the fragment shading rate state for the current pipeline - VkExtent2D fragmentSize = { 1, 1 }; - VkFragmentShadingRateCombinerOpKHR combinerOps[2]; - // The combiners determine how the different shading rate values for the pipeline, primitives and attachment are combined - if (enableShadingRate) - { - // If shading rate from attachment is enabled, we set the combiner, so that the values from the attachment are used - // Combiner for pipeline (A) and primitive (B) - Not used in this sample - combinerOps[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; - // Combiner for pipeline (A) and attachment (B), replace the pipeline default value (fragment_size) with the fragment sizes stored in the attachment - combinerOps[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR; - } - else - { - // If shading rate from attachment is disabled, we keep the value set via the dynamic state - combinerOps[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; - combinerOps[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; - } - vkCmdSetFragmentShadingRateKHR(drawCmdBuffers[i], &fragmentSize, combinerOps); - - // Render the scene - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.opaque); - scene.draw(drawCmdBuffers[i], vkglTF::RenderFlags::BindImages | vkglTF::RenderFlags::RenderOpaqueNodes, pipelineLayout); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.masked); - scene.draw(drawCmdBuffers[i], vkglTF::RenderFlags::BindImages | vkglTF::RenderFlags::RenderAlphaMaskedNodes, pipelineLayout); - - drawUI(drawCmdBuffers[i]); - vkCmdEndRenderPass(drawCmdBuffers[i]); - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } -} - -void VulkanExample::loadAssets() -{ - vkglTF::descriptorBindingFlags = vkglTF::DescriptorBindingFlags::ImageBaseColor | vkglTF::DescriptorBindingFlags::ImageNormalMap; - scene.loadFromFile(getAssetPath() + "models/sponza/sponza.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices); -} - -void VulkanExample::setupDescriptors() -{ - // Pool - const std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor set layout - const std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Pipeline layout - const std::vector setLayouts = { - descriptorSetLayout, - vkglTF::descriptorSetLayoutImage, - }; - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), 2); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Descriptor set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); -} - -// [POI] -void VulkanExample::prepareShadingRateImage() -{ - // As this is an extension, we need to manually load the extension pointers - if (!vkGetPhysicalDeviceFragmentShadingRatesKHR) { - vkGetPhysicalDeviceFragmentShadingRatesKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFragmentShadingRatesKHR")); - } - - // Get properties of this extensions, which also contains texel sizes required to setup the image - physicalDeviceShadingRateImageProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR; - VkPhysicalDeviceProperties2 deviceProperties2{}; - deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - deviceProperties2.pNext = &physicalDeviceShadingRateImageProperties; - vkGetPhysicalDeviceProperties2(physicalDevice, &deviceProperties2); - - // We need to check if the requested format for the shading rate attachment supports the required flag - const VkFormat imageFormat = VK_FORMAT_R8_UINT; - VkFormatProperties formatProperties; - vkGetPhysicalDeviceFormatProperties(physicalDevice, imageFormat, &formatProperties); - if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)) - { - throw std::runtime_error("Selected shading rate attachment image format does not fragment shading rate"); - } - - // Shading rate image size depends on shading rate texel size - // For each texel in the target image, there is a corresponding shading texel size width x height block in the shading rate image - VkExtent3D imageExtent{}; - imageExtent.width = static_cast(ceil(width / (float)physicalDeviceShadingRateImageProperties.maxFragmentShadingRateAttachmentTexelSize.width)); - imageExtent.height = static_cast(ceil(height / (float)physicalDeviceShadingRateImageProperties.maxFragmentShadingRateAttachmentTexelSize.height)); - imageExtent.depth = 1; - - VkImageCreateInfo imageCI{}; - imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageCI.imageType = VK_IMAGE_TYPE_2D; - imageCI.format = imageFormat; - imageCI.extent = imageExtent; - imageCI.mipLevels = 1; - imageCI.arrayLayers = 1; - imageCI.samples = VK_SAMPLE_COUNT_1_BIT; - imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCI.usage = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &shadingRateImage.image)); - VkMemoryRequirements memReqs{}; - vkGetImageMemoryRequirements(device, shadingRateImage.image, &memReqs); - - VkMemoryAllocateInfo memAllloc{}; - memAllloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memAllloc.allocationSize = memReqs.size; - memAllloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllloc, nullptr, &shadingRateImage.memory)); - VK_CHECK_RESULT(vkBindImageMemory(device, shadingRateImage.image, shadingRateImage.memory, 0)); - - VkImageViewCreateInfo imageViewCI{}; - imageViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageViewCI.image = shadingRateImage.image; - imageViewCI.format = VK_FORMAT_R8_UINT; - imageViewCI.subresourceRange.baseMipLevel = 0; - imageViewCI.subresourceRange.levelCount = 1; - imageViewCI.subresourceRange.baseArrayLayer = 0; - imageViewCI.subresourceRange.layerCount = 1; - imageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - VK_CHECK_RESULT(vkCreateImageView(device, &imageViewCI, nullptr, &shadingRateImage.view)); - - // The shading rates are stored in a buffer that'll be copied to the shading rate image - VkDeviceSize bufferSize = imageExtent.width * imageExtent.height * sizeof(uint8_t); - - // Fragment sizes are encoded in a single texel as follows: - // size(w) = 2^((texel/4) & 3) - // size(h)h = 2^(texel & 3) - - // Populate it with the lowest possible shading rate - uint8_t val = (4 >> 1) | (4 << 1); - uint8_t* shadingRatePatternData = new uint8_t[bufferSize]; - memset(shadingRatePatternData, val, bufferSize); - - // Get a list of available shading rate patterns - std::vector fragmentShadingRates{}; - uint32_t fragmentShadingRatesCount = 0; - vkGetPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &fragmentShadingRatesCount, nullptr); - if (fragmentShadingRatesCount > 0) { - fragmentShadingRates.resize(fragmentShadingRatesCount); - for (VkPhysicalDeviceFragmentShadingRateKHR& fragmentShadingRate : fragmentShadingRates) { - // In addition to the value, we also need to set the sType for each rate to comply with the spec or else the call to vkGetPhysicalDeviceFragmentShadingRatesKHR will result in undefined behaviour - fragmentShadingRate.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR; - } - vkGetPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &fragmentShadingRatesCount, fragmentShadingRates.data()); - } - // Create a circular pattern from the available list of fragment shading rates with decreasing sampling rates outwards (max. range, pattern) - // Shading rates returned by vkGetPhysicalDeviceFragmentShadingRatesKHR are ordered from largest to smallest - std::map patternLookup{}; - float range = 25.0f / static_cast(fragmentShadingRates.size()); - float currentRange = 8.0f; - for (size_t i = fragmentShadingRates.size() - 1; i > 0; i--) { - uint32_t rate_v = fragmentShadingRates[i].fragmentSize.width == 1 ? 0 : (fragmentShadingRates[i].fragmentSize.width >> 1); - uint32_t rate_h = fragmentShadingRates[i].fragmentSize.height == 1 ? 0 : (fragmentShadingRates[i].fragmentSize.height << 1); - patternLookup[currentRange] = rate_v | rate_h; - currentRange += range; - } - - uint8_t* ptrData = shadingRatePatternData; - for (uint32_t y = 0; y < imageExtent.height; y++) { - for (uint32_t x = 0; x < imageExtent.width; x++) { - const float deltaX = (static_cast(imageExtent.width) / 2.0f - static_cast(x)) / imageExtent.width * 100.0f; - const float deltaY = (static_cast(imageExtent.height) / 2.0f - static_cast(y)) / imageExtent.height * 100.0f; - const float dist = std::sqrt(deltaX * deltaX + deltaY * deltaY); - for (auto pattern : patternLookup) { - if (dist < pattern.first) { - *ptrData = pattern.second; - break; - } - } - ptrData++; - } - } - - // Copy the shading rate pattern to the shading rate image - - VkBuffer stagingBuffer; - VkDeviceMemory stagingMemory; - - VkBufferCreateInfo bufferCreateInfo{}; - bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferCreateInfo.size = bufferSize; - bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer)); - VkMemoryAllocateInfo memAllocInfo{}; - memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memReqs = {}; - vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory)); - VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0)); - - uint8_t* mapped; - VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void**)&mapped)); - memcpy(mapped, shadingRatePatternData, bufferSize); - vkUnmapMemory(device, stagingMemory); - - delete[] shadingRatePatternData; - - // Upload - VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.levelCount = 1; - subresourceRange.layerCount = 1; - { - VkImageMemoryBarrier imageMemoryBarrier{}; - imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageMemoryBarrier.srcAccessMask = 0; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageMemoryBarrier.image = shadingRateImage.image; - imageMemoryBarrier.subresourceRange = subresourceRange; - vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); - } - VkBufferImageCopy bufferCopyRegion{}; - bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = imageExtent.width; - bufferCopyRegion.imageExtent.height = imageExtent.height; - bufferCopyRegion.imageExtent.depth = 1; - vkCmdCopyBufferToImage(copyCmd, stagingBuffer, shadingRateImage.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion); - { - VkImageMemoryBarrier imageMemoryBarrier{}; - imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = 0; - imageMemoryBarrier.image = shadingRateImage.image; - imageMemoryBarrier.subresourceRange = subresourceRange; - vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); - } - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - vkFreeMemory(device, stagingMemory, nullptr); - vkDestroyBuffer(device, stagingBuffer, nullptr); -} - -void VulkanExample::preparePipelines() -{ - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentStateCI); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color, vkglTF::VertexComponent::Tangent }); - - shaderStages[0] = loadShader(getShadersPath() + "variablerateshading/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "variablerateshading/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - // Properties for alpha masked materials will be passed via specialization constants - struct SpecializationData { - VkBool32 alphaMask; - float alphaMaskCutoff; - } specializationData; - specializationData.alphaMask = false; - specializationData.alphaMaskCutoff = 0.5f; - const std::vector specializationMapEntries = { - vks::initializers::specializationMapEntry(0, offsetof(SpecializationData, alphaMask), sizeof(SpecializationData::alphaMask)), - vks::initializers::specializationMapEntry(1, offsetof(SpecializationData, alphaMaskCutoff), sizeof(SpecializationData::alphaMaskCutoff)), - }; - VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(specializationMapEntries, sizeof(specializationData), &specializationData); - shaderStages[1].pSpecializationInfo = &specializationInfo; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.opaque)); - - specializationData.alphaMask = true; - rasterizationStateCI.cullMode = VK_CULL_MODE_NONE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.masked)); -} - -void VulkanExample::prepareUniformBuffers() -{ - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &shaderData.buffer, - sizeof(shaderData.values))); - VK_CHECK_RESULT(shaderData.buffer.map()); - updateUniformBuffers(); -} - -void VulkanExample::updateUniformBuffers() -{ - shaderData.values.projection = camera.matrices.perspective; - shaderData.values.view = camera.matrices.view; - shaderData.values.viewPos = camera.viewPos; - shaderData.values.colorShadingRate = colorShadingRate; - memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); -} - -void VulkanExample::prepare() -{ - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; -} - -void VulkanExample::render() -{ - renderFrame(); - if (camera.updated) { - updateUniformBuffers(); - } -} - -void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) -{ - if (overlay->checkBox("Enable shading rate", &enableShadingRate)) { - buildCommandBuffers(); - } - if (overlay->checkBox("Color shading rates", &colorShadingRate)) { - updateUniformBuffers(); - } -} - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/variablerateshading/variablerateshading.h b/examples/variablerateshading/variablerateshading.h deleted file mode 100644 index 91afe1b2..00000000 --- a/examples/variablerateshading/variablerateshading.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -* Vulkan Example - Variable rate shading -* -* Copyright (C) 2020-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - vkglTF::Model scene; - - struct ShadingRateImage { - VkImage image{ VK_NULL_HANDLE }; - VkDeviceMemory memory; - VkImageView view; - } shadingRateImage; - - bool enableShadingRate = true; - bool colorShadingRate = false; - - struct ShaderData { - vks::Buffer buffer; - struct Values { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model = glm::mat4(1.0f); - glm::vec4 lightPos = glm::vec4(0.0f, 2.5f, 0.0f, 1.0f); - glm::vec4 viewPos; - int32_t colorShadingRate; - } values; - } shaderData; - - struct Pipelines { - VkPipeline opaque; - VkPipeline masked; - } pipelines; - - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; - - VkPhysicalDeviceFragmentShadingRatePropertiesKHR physicalDeviceShadingRateImageProperties{}; - VkPhysicalDeviceFragmentShadingRateFeaturesKHR enabledPhysicalDeviceShadingRateImageFeaturesKHR{}; - - PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR{ nullptr }; - PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR{ nullptr }; - PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR{ nullptr }; - - VulkanExample(); - ~VulkanExample(); - virtual void getEnabledFeatures() override; - void handleResize(); - void buildCommandBuffers() override; - void loadAssets(); - void prepareShadingRateImage(); - void setupDescriptors(); - void preparePipelines(); - void prepareUniformBuffers(); - void updateUniformBuffers(); - void prepare() override; - void setupFrameBuffer() override; - void setupRenderPass() override; - virtual void render() override; - virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay) override; -}; diff --git a/examples/vertexattributes/README.md b/examples/vertexattributes/README.md deleted file mode 100644 index 16969750..00000000 --- a/examples/vertexattributes/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# Vertex attributes - -## Synopsis - -This sample demonstrates two different ways of providing vertex data to the GPU using either interleaved or separate buffers for vertex attributes. - -## Shader interface - -The shader interface for passing the vertex attributes is the same, no matter if the data provided is coming from a single interleaved or multiple separate buffers. - -```glsl -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec4 inTangent; -``` - -## Interleaved vertex attributes - -In an interleaved vertex buffer, the components that make up a single vertex are stored after each other, so the stride of a single vertex is the sum of it's component's sizes. - -![Interleaved buffer layout](interleavedbuffer.png) - -```cpp -// Binding -const std::vector vertexInputBindingsInterleaved = { - { 0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX }, -}; - -// Attribute -const std::vector vertexInputAttributesInterleaved = { - { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos) }, - { 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal) }, - { 2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv) }, - { 3, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, tangent) }, -}; -``` - -## Separate vertex attributes - -When using separate buffers, each component is stored in it's own buffer. So e.g. the position buffer only contains vertex positions stored consecutively. - -![Interleaved buffer layout](separatebuffers.png) - -```cpp -// Bindings -const std::vector vertexInputBindingsSeparate = { - { 0, sizeof(glm::vec3), VK_VERTEX_INPUT_RATE_VERTEX }, - { 1, sizeof(glm::vec3), VK_VERTEX_INPUT_RATE_VERTEX }, - { 2, sizeof(glm::vec2), VK_VERTEX_INPUT_RATE_VERTEX }, - { 3, sizeof(glm::vec4), VK_VERTEX_INPUT_RATE_VERTEX }, -}; - -// Attributes -const std::vector vertexInputAttributesSeparate = { - { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0 }, - { 1, 1, VK_FORMAT_R32G32B32_SFLOAT, 0 }, - { 2, 2, VK_FORMAT_R32G32_SFLOAT, 0 }, - { 3, 3, VK_FORMAT_R32G32B32A32_SFLOAT, 0 }, -}; -``` \ No newline at end of file diff --git a/examples/vertexattributes/interleavedbuffer.png b/examples/vertexattributes/interleavedbuffer.png deleted file mode 100644 index 109de3a0..00000000 Binary files a/examples/vertexattributes/interleavedbuffer.png and /dev/null differ diff --git a/examples/vertexattributes/separatebuffers.png b/examples/vertexattributes/separatebuffers.png deleted file mode 100644 index abbeec2b..00000000 Binary files a/examples/vertexattributes/separatebuffers.png and /dev/null differ diff --git a/examples/vertexattributes/vertexattributes.cpp b/examples/vertexattributes/vertexattributes.cpp deleted file mode 100644 index f41966fa..00000000 --- a/examples/vertexattributes/vertexattributes.cpp +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Vulkan Example - Passing vertex attributes using interleaved and separate buffers - * - * Copyright (C) 2022-2023 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -#include "vertexattributes.h" - -void VulkanExample::loadSceneNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, Node* parent) -{ - Node node{}; - - // Get the local node matrix - // It's either made up from translation, rotation, scale or a 4x4 matrix - node.matrix = glm::mat4(1.0f); - if (inputNode.translation.size() == 3) { - node.matrix = glm::translate(node.matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); - } - if (inputNode.rotation.size() == 4) { - glm::quat q = glm::make_quat(inputNode.rotation.data()); - node.matrix *= glm::mat4(q); - } - if (inputNode.scale.size() == 3) { - node.matrix = glm::scale(node.matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); - } - if (inputNode.matrix.size() == 16) { - node.matrix = glm::make_mat4x4(inputNode.matrix.data()); - }; - - // Load node's children - if (inputNode.children.size() > 0) { - for (size_t i = 0; i < inputNode.children.size(); i++) { - loadSceneNode(input.nodes[inputNode.children[i]], input, &node); - } - } - - // If the node contains mesh data, we load vertices and indices from the buffers - // In glTF this is done via accessors and buffer views - if (inputNode.mesh > -1) { - const tinygltf::Mesh mesh = input.meshes[inputNode.mesh]; - // Iterate through all primitives of this node's mesh - for (size_t i = 0; i < mesh.primitives.size(); i++) { - const tinygltf::Primitive& glTFPrimitive = mesh.primitives[i]; - uint32_t firstIndex = static_cast(indexBuffer.size()); - uint32_t vertexStart = static_cast(vertexBuffer.size()); - uint32_t indexCount = 0; - - // Vertex attributes - const float* positionBuffer = nullptr; - const float* normalsBuffer = nullptr; - const float* texCoordsBuffer = nullptr; - const float* tangentsBuffer = nullptr; - size_t vertexCount = 0; - - // Anonymous functions to simplify buffer view access - auto getBuffer = [glTFPrimitive, input, &vertexCount](const std::string attributeName, const float* &bufferTarget) { - if (glTFPrimitive.attributes.find(attributeName) != glTFPrimitive.attributes.end()) { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find(attributeName)->second]; - const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; - bufferTarget = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - if (attributeName == "POSITION") { - vertexCount = accessor.count; - } - } - }; - - // Get buffer pointers to the vertex attributes used in this sample - getBuffer("POSITION", positionBuffer); - getBuffer("NORMAL", normalsBuffer); - getBuffer("TEXCOORD_0", texCoordsBuffer); - getBuffer("TANGENT", tangentsBuffer); - - // Append attributes to the vertex buffers - for (size_t v = 0; v < vertexCount; v++) { - - // Append interleaved attributes - Vertex vert{}; - vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f); - vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f))); - vert.uv = texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f); - vert.tangent = tangentsBuffer ? glm::make_vec4(&tangentsBuffer[v * 4]) : glm::vec4(0.0f); - vertexBuffer.push_back(vert); - - // Append separate attributes - vertexAttributeBuffers.pos.push_back(glm::make_vec3(&positionBuffer[v * 3])); - vertexAttributeBuffers.normal.push_back(glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f)))); - vertexAttributeBuffers.tangent.push_back(tangentsBuffer ? glm::make_vec4(&tangentsBuffer[v * 4]) : glm::vec4(0.0f)); - vertexAttributeBuffers.uv.push_back(texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f)); - } - - // Indices - const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.indices]; - const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; - - indexCount += static_cast(accessor.count); - - // glTF supports different component types of indices - switch (accessor.componentType) { - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { - const uint32_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: { - const uint16_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: { - const uint8_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) { - indexBuffer.push_back(buf[index] + vertexStart); - } - break; - } - default: - std::cerr << "Index component type " << accessor.componentType << " not supported!" << std::endl; - return; - } - - Primitive primitive{}; - primitive.firstIndex = firstIndex; - primitive.indexCount = indexCount; - primitive.materialIndex = glTFPrimitive.material; - node.mesh.primitives.push_back(primitive); - } - } - - if (parent) { - parent->children.push_back(node); - } - else { - nodes.push_back(node); - } -} - -VulkanExample::VulkanExample() : VulkanExampleBase() -{ - title = "Separate/interleaved vertex attribute buffers"; - camera.type = Camera::CameraType::firstperson; - camera.flipY = true; - camera.setPosition(glm::vec3(0.0f, 1.0f, 0.0f)); - camera.setRotation(glm::vec3(0.0f, -90.0f, 0.0f)); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); -} - -VulkanExample::~VulkanExample() -{ - if (device) { - vkDestroyPipeline(device, pipelines.vertexAttributesInterleaved, nullptr); - vkDestroyPipeline(device, pipelines.vertexAttributesSeparate, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr); - indices.destroy(); - shaderData.buffer.destroy(); - separateVertexBuffers.normal.destroy(); - separateVertexBuffers.pos.destroy(); - separateVertexBuffers.tangent.destroy(); - separateVertexBuffers.uv.destroy(); - interleavedVertexBuffer.destroy(); - for (Image image : scene.images) { - vkDestroyImageView(vulkanDevice->logicalDevice, image.texture.view, nullptr); - vkDestroyImage(vulkanDevice->logicalDevice, image.texture.image, nullptr); - vkDestroySampler(vulkanDevice->logicalDevice, image.texture.sampler, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr); - } - } -} - -void VulkanExample::getEnabledFeatures() -{ - enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy; -} - -void VulkanExample::drawSceneNode(VkCommandBuffer commandBuffer, Node node) -{ - if (node.mesh.primitives.size() > 0) { - PushConstBlock pushConstBlock; - glm::mat4 nodeMatrix = node.matrix; - Node* currentParent = node.parent; - while (currentParent) { - nodeMatrix = currentParent->matrix * nodeMatrix; - currentParent = currentParent->parent; - } - for (Primitive& primitive : node.mesh.primitives) { - if (primitive.indexCount > 0) { - Material& material = scene.materials[primitive.materialIndex]; - pushConstBlock.nodeMatrix = nodeMatrix; - pushConstBlock.alphaMask = (material.alphaMode == "MASK"); - pushConstBlock.alphaMaskCutoff = material.alphaCutOff; - vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstBlock), &pushConstBlock); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &material.descriptorSet, 0, nullptr); - vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0); - } - } - } - for (auto& child : node.children) { - drawSceneNode(commandBuffer, child); - } -} - -void VulkanExample::buildCommandBuffers() -{ - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - const VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - const VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - // Select the separate or interleaved vertex binding pipeline - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, vertexAttributeSettings == VertexAttributeSettings::separate ? pipelines.vertexAttributesSeparate : pipelines.vertexAttributesInterleaved); - - // Bind scene matrices descriptor to set 0 - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - // Use the same index buffer, no matter how vertex attributes are passed - vkCmdBindIndexBuffer(drawCmdBuffers[i], indices.buffer, 0, VK_INDEX_TYPE_UINT32); - - if (vertexAttributeSettings == VertexAttributeSettings::separate) { - // Using separate vertex attribute bindings requires binding multiple attribute buffers - VkDeviceSize offsets[4] = { 0, 0, 0, 0 }; - std::array buffers = { separateVertexBuffers.pos.buffer, separateVertexBuffers.normal.buffer, separateVertexBuffers.uv.buffer, separateVertexBuffers.tangent.buffer }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, static_cast(buffers.size()), buffers.data(), offsets); - } - else { - // Using interleaved attribute bindings only requires one buffer to be bound - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &interleavedVertexBuffer.buffer, offsets); - } - // Render all nodes starting at top-level - for (auto& node : nodes) { - drawSceneNode(drawCmdBuffers[i], node); - } - - drawUI(drawCmdBuffers[i]); - vkCmdEndRenderPass(drawCmdBuffers[i]); - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } -} - -void VulkanExample::loadglTFFile(std::string filename) -{ - tinygltf::Model glTFInput; - tinygltf::TinyGLTF gltfContext; - std::string error, warning; - - this->device = device; - -#if defined(__ANDROID__) - // On Android all assets are packed with the apk in a compressed form, so we need to open them using the asset manager - // We let tinygltf handle this, by passing the asset manager of our app - tinygltf::asset_manager = androidApp->activity->assetManager; -#endif - bool fileLoaded = gltfContext.LoadASCIIFromFile(&glTFInput, &error, &warning, filename); - - size_t pos = filename.find_last_of('/'); - std::string path = filename.substr(0, pos); - - if (!fileLoaded) { - vks::tools::exitFatal("Could not open the glTF file.\n\nMake sure the assets submodule has been checked out and is up-to-date.", -1); - return; - } - - // Load images - scene.images.resize(glTFInput.images.size()); - for (size_t i = 0; i < glTFInput.images.size(); i++) { - tinygltf::Image& glTFImage = glTFInput.images[i]; - scene.images[i].texture.loadFromFile(path + "/" + glTFImage.uri, VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - // Load textures - scene.textures.resize(glTFInput.textures.size()); - for (size_t i = 0; i < glTFInput.textures.size(); i++) { - scene.textures[i].imageIndex = glTFInput.textures[i].source; - } - // Load materials - scene.materials.resize(glTFInput.materials.size()); - for (size_t i = 0; i < glTFInput.materials.size(); i++) { - // We only read the most basic properties required for our sample - tinygltf::Material glTFMaterial = glTFInput.materials[i]; - // Get the base color factor - if (glTFMaterial.values.find("baseColorFactor") != glTFMaterial.values.end()) { - scene.materials[i].baseColorFactor = glm::make_vec4(glTFMaterial.values["baseColorFactor"].ColorFactor().data()); - } - // Get base color texture index - if (glTFMaterial.values.find("baseColorTexture") != glTFMaterial.values.end()) { - scene.materials[i].baseColorTextureIndex = glTFMaterial.values["baseColorTexture"].TextureIndex(); - } - // Get the normal map texture index - if (glTFMaterial.additionalValues.find("normalTexture") != glTFMaterial.additionalValues.end()) { - scene.materials[i].normalTextureIndex = glTFMaterial.additionalValues["normalTexture"].TextureIndex(); - } - // Get some additional material parameters that are used in this sample - scene.materials[i].alphaMode = glTFMaterial.alphaMode; - scene.materials[i].alphaCutOff = (float)glTFMaterial.alphaCutoff; - } - // Load nodes - const tinygltf::Scene& scene = glTFInput.scenes[0]; - for (size_t i = 0; i < scene.nodes.size(); i++) { - const tinygltf::Node node = glTFInput.nodes[scene.nodes[i]]; - loadSceneNode(node, glTFInput, nullptr); - } - - uploadVertexData(); -} - -void VulkanExample::uploadVertexData() -{ - // Upload vertex and index buffers - - // Anonymous functions to simplify buffer creation - // Create a staging buffer used as a source for copies - auto createStagingBuffer = [this](vks::Buffer& buffer, void* data, VkDeviceSize size) { - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &buffer, size, data)); - }; - // Create a device local buffer used as a target for copies - auto createDeviceBuffer = [this](vks::Buffer& buffer, VkDeviceSize size, VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) { - VK_CHECK_RESULT(vulkanDevice->createBuffer(usageFlags | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &buffer, size)); - }; - - VkCommandBuffer copyCmd; - VkBufferCopy copyRegion{}; - - /* - Interleaved vertex attributes - We create one single buffer containing the interleaved vertex attributes - */ - size_t vertexBufferSize = vertexBuffer.size() * sizeof(Vertex); - vks::Buffer vertexStaging; - createStagingBuffer(vertexStaging, vertexBuffer.data(), vertexBufferSize); - createDeviceBuffer(interleavedVertexBuffer, vertexStaging.size); - - // Copy data from staging buffer (host) do device local buffer (gpu) - copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - copyRegion.size = vertexBufferSize; - vkCmdCopyBuffer(copyCmd, vertexStaging.buffer, interleavedVertexBuffer.buffer, 1, ©Region); - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - vertexStaging.destroy(); - - /* - Separate vertex attributes - We create multiple separate buffers for each of the vertex attributes (position, normals, etc.) - */ - std::array stagingBuffers; - createStagingBuffer(stagingBuffers[0], vertexAttributeBuffers.pos.data(), vertexAttributeBuffers.pos.size() * sizeof(vertexAttributeBuffers.pos[0])); - createStagingBuffer(stagingBuffers[1], vertexAttributeBuffers.normal.data(), vertexAttributeBuffers.normal.size() * sizeof(vertexAttributeBuffers.normal[0])); - createStagingBuffer(stagingBuffers[2], vertexAttributeBuffers.uv.data(), vertexAttributeBuffers.uv.size() * sizeof(vertexAttributeBuffers.uv[0])); - createStagingBuffer(stagingBuffers[3], vertexAttributeBuffers.tangent.data(), vertexAttributeBuffers.tangent.size() * sizeof(vertexAttributeBuffers.tangent[0])); - - createDeviceBuffer(separateVertexBuffers.pos, stagingBuffers[0].size); - createDeviceBuffer(separateVertexBuffers.normal, stagingBuffers[1].size); - createDeviceBuffer(separateVertexBuffers.uv, stagingBuffers[2].size); - createDeviceBuffer(separateVertexBuffers.tangent, stagingBuffers[3].size); - - // Stage - std::vector attributeBuffers = { - separateVertexBuffers.pos, - separateVertexBuffers.normal, - separateVertexBuffers.uv, - separateVertexBuffers.tangent, - }; - - // Copy data from staging buffer (host) do device local buffer (gpu) - copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - for (size_t i = 0; i < attributeBuffers.size(); i++) { - copyRegion.size = attributeBuffers[i].size; - vkCmdCopyBuffer(copyCmd, stagingBuffers[i].buffer, attributeBuffers[i].buffer, 1, ©Region); - } - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - - for (size_t i = 0; i < 4; i++) { - stagingBuffers[i].destroy(); - } - - /* - Index buffer - The index buffer is always the same, no matter how we pass the vertex attributes - */ - size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t); - vks::Buffer indexStaging; - createStagingBuffer(indexStaging, indexBuffer.data(), indexBufferSize); - createDeviceBuffer(indices, indexStaging.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); - // Copy data from staging buffer (host) do device local buffer (gpu) - copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - copyRegion.size = indexBufferSize; - vkCmdCopyBuffer(copyCmd, indexStaging.buffer, indices.buffer, 1, ©Region); - vulkanDevice->flushCommandBuffer(copyCmd, queue, true); - // Free staging resources - indexStaging.destroy(); -} - -void VulkanExample::loadAssets() -{ - loadglTFFile(getAssetPath() + "models/sponza/sponza.gltf"); -} - -void VulkanExample::setupDescriptors() -{ - // One ubo to pass dynamic data to the shader - // Two combined image samplers per material as each material uses color and normal maps - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(scene.materials.size()) * 2), - }; - // One set for matrices and one per model image/texture - const uint32_t maxSetCount = static_cast(scene.images.size()) + 1; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - // Descriptor set layout for passing matrices - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices)); - // Descriptor set layout for passing material textures - setLayoutBindings = { - // Color map - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - // Normal map - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), - }; - descriptorSetLayoutCI.pBindings = setLayoutBindings.data(); - descriptorSetLayoutCI.bindingCount = 2; - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures)); - - // Pipeline layout using both descriptor sets (set 0 = matrices, set 1 = material) - std::array setLayouts = { descriptorSetLayouts.matrices, descriptorSetLayouts.textures }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - // We will use push constants to push the local matrices of a primitive to the vertex shader - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushConstBlock), 0); - // Push constant ranges are part of the pipeline layout - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - // Descriptor set for scene matrices - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - - // Descriptor sets for the materials - for (auto& material : scene.materials) { - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &material.descriptorSet)); - VkDescriptorImageInfo colorMap = scene.images[material.baseColorTextureIndex].texture.descriptor; - VkDescriptorImageInfo normalMap = scene.images[material.normalTextureIndex].texture.descriptor; - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(material.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &colorMap), - vks::initializers::writeDescriptorSet(material.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &normalMap), - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } -} - -void VulkanExample::preparePipelines() -{ - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentStateCI); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); - VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pVertexInputState = &vertexInputStateCI; - pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; - pipelineCI.pRasterizationState = &rasterizationStateCI; - pipelineCI.pColorBlendState = &colorBlendStateCI; - pipelineCI.pMultisampleState = &multisampleStateCI; - pipelineCI.pViewportState = &viewportStateCI; - pipelineCI.pDepthStencilState = &depthStencilStateCI; - pipelineCI.pDynamicState = &dynamicStateCI; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - - shaderStages[0] = loadShader(getShadersPath() + "vertexattributes/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "vertexattributes/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - // Interleaved vertex attributes - // One Binding (one buffer) and multiple attributes - const std::vector vertexInputBindingsInterleaved = { - { 0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX }, - }; - const std::vector vertexInputAttributesInterleaved = { - { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos) }, - { 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal) }, - { 2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv) }, - { 3, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, tangent) }, - }; - - vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(vertexInputBindingsInterleaved, vertexInputAttributesInterleaved); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.vertexAttributesInterleaved)); - - // Separate vertex attribute - // Multiple bindings (for each attribute buffer) and multiple attribues - const std::vector vertexInputBindingsSeparate = { - { 0, sizeof(glm::vec3), VK_VERTEX_INPUT_RATE_VERTEX }, - { 1, sizeof(glm::vec3), VK_VERTEX_INPUT_RATE_VERTEX }, - { 2, sizeof(glm::vec2), VK_VERTEX_INPUT_RATE_VERTEX }, - { 3, sizeof(glm::vec4), VK_VERTEX_INPUT_RATE_VERTEX }, - }; - const std::vector vertexInputAttributesSeparate = { - { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0 }, - { 1, 1, VK_FORMAT_R32G32B32_SFLOAT, 0 }, - { 2, 2, VK_FORMAT_R32G32_SFLOAT, 0 }, - { 3, 3, VK_FORMAT_R32G32B32A32_SFLOAT, 0 }, - }; - - vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(vertexInputBindingsSeparate, vertexInputAttributesSeparate); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.vertexAttributesSeparate)); -} - -void VulkanExample::prepareUniformBuffers() -{ - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &shaderData.buffer, - sizeof(shaderData.values))); - VK_CHECK_RESULT(shaderData.buffer.map()); - updateUniformBuffers(); -} - -void VulkanExample::updateUniformBuffers() -{ - shaderData.values.projection = camera.matrices.perspective; - shaderData.values.view = camera.matrices.view; - shaderData.values.viewPos = camera.viewPos; - memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); -} - -void VulkanExample::prepare() -{ - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; -} - -void VulkanExample::render() -{ - updateUniformBuffers(); - renderFrame(); -} - -void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) -{ - if (overlay->header("Vertex buffer attributes")) { - bool interleaved = (vertexAttributeSettings == VertexAttributeSettings::interleaved); - bool separate = (vertexAttributeSettings == VertexAttributeSettings::separate); - if (overlay->radioButton("Interleaved", interleaved)) { - vertexAttributeSettings = VertexAttributeSettings::interleaved; - buildCommandBuffers(); - } - if (overlay->radioButton("Separate", separate)) { - vertexAttributeSettings = VertexAttributeSettings::separate; - buildCommandBuffers(); - } - } -} - -VULKAN_EXAMPLE_MAIN() diff --git a/examples/vertexattributes/vertexattributes.h b/examples/vertexattributes/vertexattributes.h deleted file mode 100644 index 7e16dafb..00000000 --- a/examples/vertexattributes/vertexattributes.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Vulkan Example - Passing vertex attributes using interleaved and separate buffers - * - * Copyright (C) 2022-2023 by Sascha Willems - www.saschawillems.de - * - * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - */ - -#define TINYGLTF_IMPLEMENTATION -#define STB_IMAGE_IMPLEMENTATION -#define TINYGLTF_NO_STB_IMAGE_WRITE -#define TINYGLTF_NO_STB_IMAGE -#define TINYGLTF_NO_EXTERNAL_IMAGE -#ifdef VK_USE_PLATFORM_ANDROID_KHR -#define TINYGLTF_ANDROID_LOAD_FROM_ASSETS -#endif -#include "tiny_gltf.h" - -#include "vulkanexamplebase.h" - -struct PushConstBlock { - glm::mat4 nodeMatrix; - uint32_t alphaMask; - float alphaMaskCutoff; -}; - -struct Material { - glm::vec4 baseColorFactor = glm::vec4(1.0f); - uint32_t baseColorTextureIndex; - uint32_t normalTextureIndex; - std::string alphaMode = "OPAQUE"; - float alphaCutOff; - VkDescriptorSet descriptorSet; -}; - -struct Image { - vks::Texture2D texture; -}; - -struct Texture { - int32_t imageIndex; -}; - -// Layout for the interleaved vertex attributes -struct Vertex { - glm::vec3 pos; - glm::vec3 normal; - glm::vec2 uv; - glm::vec4 tangent; -}; - -struct Primitive { - uint32_t firstIndex; - uint32_t indexCount; - int32_t materialIndex; -}; -struct Mesh { - std::vector primitives; -}; -struct Node; -struct Node { - Node* parent; - std::vector children; - Mesh mesh; - glm::mat4 matrix; -}; - -std::vector nodes; - -class VulkanExample : public VulkanExampleBase -{ -public: - enum VertexAttributeSettings { interleaved, separate }; - VertexAttributeSettings vertexAttributeSettings = separate; - - // Used to store indices and vertices from glTF to be uploaded to the GPU - std::vector indexBuffer; - std::vector vertexBuffer; - struct VertexAttributes { - std::vector uv; - std::vector pos, normal; - std::vector tangent; - } vertexAttributeBuffers; - - // Buffers for the separate vertex attributes - struct SeparateVertexBuffers { - vks::Buffer pos, normal, uv, tangent; - } separateVertexBuffers; - - // Single vertex buffer for all primitives - vks::Buffer interleavedVertexBuffer; - - // Index buffer for all primitives of the scene - vks::Buffer indices; - - struct ShaderData { - vks::Buffer buffer; - struct Values { - glm::mat4 projection; - glm::mat4 view; - glm::vec4 lightPos = glm::vec4(0.0f, 2.5f, 0.0f, 1.0f); - glm::vec4 viewPos; - } values; - } shaderData; - - struct Pipelines { - VkPipeline vertexAttributesInterleaved; - VkPipeline vertexAttributesSeparate; - } pipelines; - VkPipelineLayout pipelineLayout; - - struct DescriptorSetLayouts { - VkDescriptorSetLayout matrices; - VkDescriptorSetLayout textures; - } descriptorSetLayouts; - VkDescriptorSet descriptorSet; - - struct Scene { - std::vector images; - std::vector textures; - std::vector materials; - } scene; - - VulkanExample(); - ~VulkanExample(); - virtual void getEnabledFeatures(); - void buildCommandBuffers(); - void uploadVertexData(); - void loadglTFFile(std::string filename); - void loadAssets(); - void setupDescriptors(); - void preparePipelines(); - void prepareUniformBuffers(); - void updateUniformBuffers(); - void prepare(); - void loadSceneNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, Node* parent); - void drawSceneNode(VkCommandBuffer commandBuffer, Node node); - virtual void render(); - virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); -}; diff --git a/examples/viewportarray/viewportarray.cpp b/examples/viewportarray/viewportarray.cpp deleted file mode 100644 index 7c022ed1..00000000 --- a/examples/viewportarray/viewportarray.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* -* Vulkan Example - Viewport array with single pass rendering using geometry shaders -* -* Copyright (C) 2017-2023 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - vkglTF::Model scene; - - struct UniformDataGS { - glm::mat4 projection[2]; - glm::mat4 modelview[2]; - glm::vec4 lightPos = glm::vec4(-2.5f, -3.5f, 0.0f, 1.0f); - } uniformDataGS; - vks::Buffer uniformBufferGS; - - VkPipeline pipeline{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - // Camera and view properties - float eyeSeparation = 0.08f; - const float focalLength = 0.5f; - const float fov = 90.0f; - const float zNear = 0.1f; - const float zFar = 256.0f; - - VulkanExample() : VulkanExampleBase() - { - title = "Viewport arrays"; - camera.type = Camera::CameraType::firstperson; - camera.setRotation(glm::vec3(0.0f, 90.0f, 0.0f)); - camera.setTranslation(glm::vec3(7.0f, 3.2f, 0.0f)); - camera.setMovementSpeed(5.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - uniformBufferGS.destroy(); - } - } - - // Enable physical device features required for this example - virtual void getEnabledFeatures() - { - // Geometry shader support is required for this example - if (deviceFeatures.geometryShader) { - enabledFeatures.geometryShader = VK_TRUE; - } - else { - vks::tools::exitFatal("Selected GPU does not support geometry shaders!", VK_ERROR_FEATURE_NOT_PRESENT); - } - // Multiple viewports must be supported - if (deviceFeatures.multiViewport) { - enabledFeatures.multiViewport = VK_TRUE; - } - else { - vks::tools::exitFatal("Selected GPU does not support multi viewports!", VK_ERROR_FEATURE_NOT_PRESENT); - } - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - // Set target frame buffer - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - // We render to two viewports simultaneously, so we need to viewports and two scissor rectangles - // 0 = right, 1 = left - VkViewport viewports[2] = { - { (float)width / 2.0f, 0, (float)width / 2.0f, (float)height, 0.0, 1.0f }, - { 0, 0, (float)width / 2.0f, (float)height, 0.0, 1.0f }, - }; - vkCmdSetViewport(drawCmdBuffers[i], 0, 2, viewports); - - VkRect2D scissorRects[2] = { - vks::initializers::rect2D(width/2, height, width / 2, 0), - vks::initializers::rect2D(width/2, height, 0, 0), - }; - vkCmdSetScissor(drawCmdBuffers[i], 0, 2, scissorRects); - - vkCmdSetLineWidth(drawCmdBuffers[i], 1.0f); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - scene.draw(drawCmdBuffers[i]); - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void loadAssets() - { - scene.loadFromFile(getAssetPath() + "models/sampleroom.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), 1); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT, 0) // Binding 1: Geometry shader ubo - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferGS.descriptor), // Binding 0 :Geometry shader ubo - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - // We use two viewports - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(2, 2, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.renderPass = renderPass; - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); - - shaderStages[0] = loadShader(getShadersPath() + "viewportarray/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "viewportarray/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - // A geometry shader is used to output geometry to multiple viewports in one single pass - // See the "invocations" decorator of the layout input in the shader - shaderStages[2] = loadShader(getShadersPath() + "viewportarray/multiview.geom.spv", VK_SHADER_STAGE_GEOMETRY_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - // Geometry shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBufferGS, sizeof(UniformDataGS))); - // Map persistent - VK_CHECK_RESULT(uniformBufferGS.map()); - } - - void updateUniformBuffers() - { - // Geometry shader matrices for the two viewports - // See http://paulbourke.net/stereographics/stereorender/ - - // Calculate some variables - float aspectRatio = (float)(width * 0.5f) / (float)height; - float wd2 = zNear * tan(glm::radians(fov / 2.0f)); - float ndfl = zNear / focalLength; - float left, right; - float top = wd2; - float bottom = -wd2; - - glm::vec3 camFront; - camFront.x = -cos(glm::radians(camera.rotation.x)) * sin(glm::radians(camera.rotation.y)); - camFront.y = sin(glm::radians(camera.rotation.x)); - camFront.z = cos(glm::radians(camera.rotation.x)) * cos(glm::radians(camera.rotation.y)); - camFront = glm::normalize(camFront); - glm::vec3 camRight = glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))); - - glm::mat4 rotM = glm::mat4(1.0f); - glm::mat4 transM; - - rotM = glm::rotate(rotM, glm::radians(camera.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); - rotM = glm::rotate(rotM, glm::radians(camera.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - rotM = glm::rotate(rotM, glm::radians(camera.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); - - // Left eye - left = -aspectRatio * wd2 + 0.5f * eyeSeparation * ndfl; - right = aspectRatio * wd2 + 0.5f * eyeSeparation * ndfl; - - transM = glm::translate(glm::mat4(1.0f), camera.position - camRight * (eyeSeparation / 2.0f)); - - uniformDataGS.projection[0] = glm::frustum(left, right, bottom, top, zNear, zFar); - uniformDataGS.modelview[0] = rotM * transM; - - // Right eye - left = -aspectRatio * wd2 - 0.5f * eyeSeparation * ndfl; - right = aspectRatio * wd2 - 0.5f * eyeSeparation * ndfl; - - transM = glm::translate(glm::mat4(1.0f), camera.position + camRight * (eyeSeparation / 2.0f)); - - uniformDataGS.projection[1] = glm::frustum(left, right, bottom, top, zNear, zFar); - uniformDataGS.modelview[1] = rotM * transM; - - memcpy(uniformBufferGS.mapped, &uniformDataGS, sizeof(uniformDataGS)); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - - virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) - { - if (overlay->header("Settings")) { - if (overlay->sliderFloat("Eye separation", &eyeSeparation, -1.0f, 1.0f)) { - updateUniformBuffers(); - } - } - } - -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/vulkanscene/vulkanscene.cpp b/examples/vulkanscene/vulkanscene.cpp deleted file mode 100644 index a900f3c0..00000000 --- a/examples/vulkanscene/vulkanscene.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* -* Vulkan Demo Scene -* -* Don't take this a an example, it's more of a playground -* -* Copyright (C) 2016-2025 by Sascha Willems - www.saschawillems.de -* -* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -*/ - -#include "vulkanexamplebase.h" -#include "VulkanglTFModel.h" - -class VulkanExample : public VulkanExampleBase -{ -public: - struct DemoModel { - vkglTF::Model* glTF; - VkPipeline *pipeline; - }; - std::vector demoModels; - vks::TextureCubeMap skybox; - - struct UniformData { - glm::mat4 projection; - glm::mat4 model; - glm::mat4 normal; - glm::mat4 view; - glm::vec4 lightPos; - } uniformData; - vks::Buffer uniformBuffer; - - struct { - VkPipeline logos{ VK_NULL_HANDLE }; - VkPipeline models{ VK_NULL_HANDLE }; - VkPipeline skybox{ VK_NULL_HANDLE }; - } pipelines; - - VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; - VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - - glm::vec4 lightPos = glm::vec4(1.0f, 4.0f, 0.0f, 0.0f); - - VulkanExample() : VulkanExampleBase() - { - title = "Vulkan Demo Scene"; - camera.type = Camera::CameraType::lookat; - //camera.flipY = true; - camera.setPosition(glm::vec3(0.0f, 0.0f, -3.75f)); - camera.setRotation(glm::vec3(15.0f, 0.0f, 0.0f)); - camera.setRotationSpeed(0.5f); - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); - } - - ~VulkanExample() - { - if (device) { - vkDestroyPipeline(device, pipelines.logos, nullptr); - vkDestroyPipeline(device, pipelines.models, nullptr); - vkDestroyPipeline(device, pipelines.skybox, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - for (auto demoModel : demoModels) { - delete demoModel.glTF; - } - uniformBuffer.destroy(); - skybox.destroy(); - } - } - - void loadAssets() - { - // Models - std::vector modelFiles = { "cube.gltf", "vulkanscenelogos.gltf", "vulkanscenebackground.gltf", "vulkanscenemodels.gltf" }; - std::vector modelPipelines = { &pipelines.skybox, &pipelines.logos, &pipelines.models, &pipelines.models }; - for (auto i = 0; i < modelFiles.size(); i++) { - DemoModel model; - const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY; - model.pipeline = modelPipelines[i]; - model.glTF = new vkglTF::Model(); - model.glTF->loadFromFile(getAssetPath() + "models/" + modelFiles[i], vulkanDevice, queue, glTFLoadingFlags); - demoModels.push_back(model); - } - // Textures - skybox.loadFromFile(getAssetPath() + "textures/cubemap_vulkan.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - } - - void setupDescriptors() - { - // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Layout - std::vector setLayoutBindings = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - // Binding 1 : Fragment shader color map image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - - // Set - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - - std::vector writeDescriptorSets = { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), - // Binding 1 : Fragment shader image sampler - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &skybox.descriptor) - }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - } - - void preparePipelines() - { - // Layout - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - // Pipelines - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE,0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = static_cast(shaderStages.size()); - pipelineCI.pStages = shaderStages.data(); - pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::UV, vkglTF::VertexComponent::Color });; - - // Default mesh rendering pipeline - shaderStages[0] = loadShader(getShadersPath() + "vulkanscene/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "vulkanscene/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.models)); - - // Pipeline for the logos - shaderStages[0] = loadShader(getShadersPath() + "vulkanscene/logo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "vulkanscene/logo.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.logos)); - - // Pipeline for the skybox - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - depthStencilState.depthWriteEnable = VK_FALSE; - shaderStages[0] = loadShader(getShadersPath() + "vulkanscene/skybox.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getShadersPath() + "vulkanscene/skybox.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.skybox)); - } - - // Prepare and initialize uniform buffer containing shader uniforms - void prepareUniformBuffers() - { - vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,&uniformBuffer, sizeof(uniformData)); - VK_CHECK_RESULT(uniformBuffer.map()); - } - - void updateUniformBuffers() - { - uniformData.projection = camera.matrices.perspective; - uniformData.view = camera.matrices.view; - uniformData.model = glm::mat4(1.0f); - uniformData.normal = glm::inverseTranspose(uniformData.view * uniformData.model); - uniformData.lightPos = lightPos; - memcpy(uniformBuffer.mapped, &uniformData, sizeof(uniformData)); - } - - void buildCommandBuffers() - { - VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); - - VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) - { - renderPassBeginInfo.framebuffer = frameBuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - - VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); - - for (auto model : demoModels) { - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, *model.pipeline); - model.glTF->draw(drawCmdBuffers[i]); - } - - drawUI(drawCmdBuffers[i]); - - vkCmdEndRenderPass(drawCmdBuffers[i]); - - VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - } - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VulkanExampleBase::submitFrame(); - } - - void prepare() - { - VulkanExampleBase::prepare(); - loadAssets(); - prepareUniformBuffers(); - setupDescriptors(); - preparePipelines(); - buildCommandBuffers(); - prepared = true; - } - - virtual void render() - { - if (!prepared) - return; - updateUniformBuffers(); - draw(); - } - -}; - -VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/external/ktx/other_include/other_include/KHR/khrplatform.h b/external/ktx/other_include/other_include/KHR/khrplatform.h new file mode 100644 index 00000000..c9e6f17d --- /dev/null +++ b/external/ktx/other_include/other_include/KHR/khrplatform.h @@ -0,0 +1,282 @@ +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2009 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $ + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by sending them to the public Khronos Bugzilla + * (http://khronos.org/bugzilla) by filing a bug against product + * "Khronos (general)" component "Registry". + * + * A predefined template which fills in some of the bug fields can be + * reached using http://tinyurl.com/khrplatform-h-bugreport, but you + * must create a Bugzilla login first. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(_WIN32) && !defined(__SCITECH_SNAP__) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef _WIN64 +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ diff --git a/external/stb/stb_font_consolas_24_latin1.inl b/external/stb/stb_font_consolas_24_latin1.inl deleted file mode 100644 index 12eedd2f..00000000 --- a/external/stb/stb_font_consolas_24_latin1.inl +++ /dev/null @@ -1,734 +0,0 @@ -// Font generated by stb_font_inl_generator.c (4/1 bpp) -// -// Following instructions show how to use the only included font, whatever it is, in -// a generic way so you can replace it with any other font by changing the include. -// To use multiple fonts, replace STB_SOMEFONT_* below with STB_FONT_consolas_24_latin1_*, -// and separately install each font. Note that the CREATE function call has a -// totally different name; it's just 'stb_font_consolas_24_latin1'. -// -/* // Example usage: - -static stb_fontchar fontdata[STB_SOMEFONT_NUM_CHARS]; - -static void init(void) -{ - // optionally replace both STB_SOMEFONT_BITMAP_HEIGHT with STB_SOMEFONT_BITMAP_HEIGHT_POW2 - static unsigned char fontpixels[STB_SOMEFONT_BITMAP_HEIGHT][STB_SOMEFONT_BITMAP_WIDTH]; - STB_SOMEFONT_CREATE(fontdata, fontpixels, STB_SOMEFONT_BITMAP_HEIGHT); - ... create texture ... - // for best results rendering 1:1 pixels texels, use nearest-neighbor sampling - // if allowed to scale up, use bilerp -} - -// This function positions characters on integer coordinates, and assumes 1:1 texels to pixels -// Appropriate if nearest-neighbor sampling is used -static void draw_string_integer(int x, int y, char *str) // draw with top-left point x,y -{ - ... use texture ... - ... turn on alpha blending and gamma-correct alpha blending ... - glBegin(GL_QUADS); - while (*str) { - int char_codepoint = *str++; - stb_fontchar *cd = &fontdata[char_codepoint - STB_SOMEFONT_FIRST_CHAR]; - glTexCoord2f(cd->s0, cd->t0); glVertex2i(x + cd->x0, y + cd->y0); - glTexCoord2f(cd->s1, cd->t0); glVertex2i(x + cd->x1, y + cd->y0); - glTexCoord2f(cd->s1, cd->t1); glVertex2i(x + cd->x1, y + cd->y1); - glTexCoord2f(cd->s0, cd->t1); glVertex2i(x + cd->x0, y + cd->y1); - // if bilerping, in D3D9 you'll need a half-pixel offset here for 1:1 to behave correct - x += cd->advance_int; - } - glEnd(); -} - -// This function positions characters on float coordinates, and doesn't require 1:1 texels to pixels -// Appropriate if bilinear filtering is used -static void draw_string_float(float x, float y, char *str) // draw with top-left point x,y -{ - ... use texture ... - ... turn on alpha blending and gamma-correct alpha blending ... - glBegin(GL_QUADS); - while (*str) { - int char_codepoint = *str++; - stb_fontchar *cd = &fontdata[char_codepoint - STB_SOMEFONT_FIRST_CHAR]; - glTexCoord2f(cd->s0f, cd->t0f); glVertex2f(x + cd->x0f, y + cd->y0f); - glTexCoord2f(cd->s1f, cd->t0f); glVertex2f(x + cd->x1f, y + cd->y0f); - glTexCoord2f(cd->s1f, cd->t1f); glVertex2f(x + cd->x1f, y + cd->y1f); - glTexCoord2f(cd->s0f, cd->t1f); glVertex2f(x + cd->x0f, y + cd->y1f); - // if bilerping, in D3D9 you'll need a half-pixel offset here for 1:1 to behave correct - x += cd->advance; - } - glEnd(); -} -*/ - -#pragma once - -#ifndef STB_FONTCHAR__TYPEDEF -#define STB_FONTCHAR__TYPEDEF -typedef struct -{ - // coordinates if using integer positioning - float s0,t0,s1,t1; - signed short x0,y0,x1,y1; - int advance_int; - // coordinates if using floating positioning - float s0f,t0f,s1f,t1f; - float x0f,y0f,x1f,y1f; - float advance; -} stb_fontchar; -#endif - -#define STB_FONT_consolas_24_latin1_BITMAP_WIDTH 256 -#define STB_FONT_consolas_24_latin1_BITMAP_HEIGHT 170 -#define STB_FONT_consolas_24_latin1_BITMAP_HEIGHT_POW2 256 - -#define STB_FONT_consolas_24_latin1_FIRST_CHAR 32 -#define STB_FONT_consolas_24_latin1_NUM_CHARS 224 - -#define STB_FONT_consolas_24_latin1_LINE_SPACING 16 - -static unsigned int stb__consolas_24_latin1_pixels[]={ - 0x08262131,0xff904400,0x3ffe1fff,0x3b2206ff,0x2007913f,0x0000defa, - 0x64c00f32,0x0de5c402,0x00a614c0,0x4002ae62,0x98014c19,0x01aa881c, - 0x00d54400,0xb880154c,0x8330020b,0x1e980029,0xaa7d5dd4,0x2001d94f, - 0x3332a6e8,0x999ff0ff,0x37ffa207,0x2600df12,0x8000fffd,0x3fa005fd, - 0xfdff700f,0x8ffc409f,0x3ea02ff8,0x200dffff,0x0bfe0ff8,0x7d407ee0, - 0xfd10001f,0x9fff5007,0xcffff880,0x1ff104eb,0x320017fc,0x7d77e40f, - 0x17ee9f54,0xfd027ec0,0x7dc01fe1,0x0037c40d,0xb0017f22,0xffe8007f, - 0x7dc3fd80,0x741ff104,0x59ff701f,0x7401dfd7,0x2003f60e,0x3fa200fc, - 0x0ff44001,0x7dc6fdc0,0x32236604,0x3ba00eff,0x31003f60,0xdf90dd57, - 0xd93ea9f5,0x037e403f,0x803fc3fa,0x06f882fd,0x2006f980,0xa8800098, - 0xf903fb81,0x88040401,0x1ff441ff,0x0fb00000,0x00000000,0x00020000, - 0xffffa800,0xfadfb86f,0x7fc49f54,0x803ff301,0x200ff0fe,0x06f880fe, - 0x0000ff00,0x05f88000,0x40000fe6,0x0ff504fc,0x81540153,0x100affb9, - 0x22001573,0x31000ab9,0x26200157,0x731000ab,0xcffb8015,0x7dc4ffda, - 0x89f54fad,0x3fe80ff9,0x0ff0fe80,0x3e203fa0,0x807ddb36,0x01dd107f, - 0xdddb076c,0x1fb8bddd,0x1dd12fc0,0x3ff076c0,0x3f60ffc0,0xe98ff102, - 0xa84fffff,0x00dfffff,0x37ffffea,0x3fffea00,0x3fea00df,0x2a00dfff, - 0x80dfffff,0x3bb61ff8,0x3eb3ea3f,0x7f909f54,0xfd005fa8,0x7f401fe1, - 0xffaef880,0x1fe05ffe,0xdf504fd8,0xfffffff8,0x9db33746,0x09fb1b6b, - 0x80ff1bea,0x817ec2fd,0x33fe67f8,0x7dc3acfa,0x0efebacf,0xebacffb8, - 0xcffb80ef,0xb80efeba,0xefebacff,0xbacffb80,0x27e40efe,0x20df59f1, - 0x509f54fa,0x003fd8bf,0x401fe1fd,0x9fff107e,0x7407fe61,0x20ff500f, - 0x6f9803fd,0x777ccfe2,0x7fa8db6f,0x37cc7fb0,0x5fb0ff60,0x3fe9fe20, - 0x3ff105f3,0x7c43fe88,0x21ff441f,0x7f441ff8,0x220ffc43,0x0ffc43fe, - 0x3ff0ffa2,0x267f97d4,0x9f54fadf,0x1ff8ff10,0x1fe1fd00,0x7c417e20, - 0x704fb84f,0x217f405f,0xf9800ff8,0x47f47ea6,0xfd0f95f8,0x260ff885, - 0x21fe406f,0x2ff102fd,0x207ea6f9,0x8ff504fc,0x8ff504fc,0x8ff504fc, - 0x8ff504fc,0x8ff504fc,0x3fd3e47f,0x553eafea,0x261ff04f,0x1fd000ff, - 0xefcc81fe,0x260ff101,0x9bfb105f,0x7d45fb81,0x64df3005,0x9f34f98f, - 0x517ee1f2,0x407f98bf,0x817ec2fd,0x5cbf57f8,0x201ff80f,0x807fe1ff, - 0x807fe1ff,0x807fe1ff,0x807fe1ff,0xf8df31ff,0x47e4bf65,0x203514fa, - 0x00df52fd,0x107f87f4,0x7c403fff,0x440df306,0x7fc41ffe,0x4c00bf60, - 0x97ddf66f,0xf10db2fa,0x2217ec1f,0x20ff407f,0x2ff102fd,0x7c1f64fb, - 0xff17ec07,0x1fe2fd80,0x03fc5fb0,0x407f8bf6,0x4cdf32fd,0x9d4ff22f, - 0x9f7004fa,0xfe8013ee,0x6cc40ff0,0x20df103f,0x3bf506f9,0x7c4ff601, - 0xd9be6007,0x47f23f96,0x227fb06d,0x203ff07f,0x17ec0ff8,0x4df57f88, - 0x406f986e,0x80df33fd,0x80df33fd,0x80df33fd,0x80df33fd,0x64ff13fd, - 0x2a0bf60f,0x29f9004f,0x3fa005fa,0x1be00ff0,0x5fa837c4,0xfa801f90, - 0x4c009f76,0x87edba6f,0x2a09f0fd,0x3209f76f,0xb0bf704f,0x4dfe205f, - 0xf30bf0ff,0xf33fc80d,0xf33fc80d,0xf33fc80d,0xf33fc80d,0x3e3fc80d, - 0x03fd1ba7,0x3f6009f5,0x7400ff13,0x3a00ff0f,0x906f880f,0x401fa07f, - 0x001fe9ff,0xf96e9be6,0x017cdfe3,0x203fd3ff,0x7fd43ff9,0xf102fd81, - 0x27d7fecf,0xfb01fe63,0xfb01fe65,0xfb01fe65,0xfb01fe65,0xfb01fe65, - 0x1fc4ff45,0x9f501ff1,0xfe8bfe00,0x3e1fd001,0x101fd007,0x40df50df, - 0xfbf9007e,0x26f9800d,0xfdb9f56d,0x7e401fb7,0x7fdc06fd,0xb02ffede, - 0x89fe205f,0x4feefffc,0x1fe80ff1,0x1fe80ff1,0x1fe80ff1,0x1fe80ff1, - 0x1fe80ff1,0xb87ef7f2,0x2a9f505f,0x647f984f,0x21fd002f,0x01fd007f, - 0xfb99dff1,0x803f403f,0x4003fff8,0x6c5f26f9,0x01ffe8ef,0x401fffc4, - 0x01dfffda,0x2fd40ff2,0x0e77ff4c,0x3fe203ff,0x7c407fe0,0x4407fe0f, - 0x407fe0ff,0x07fe0ff8,0xff107fc4,0x807fd4fd,0x509f54fa,0x004fa8bf, - 0x401fe1fd,0xfff880fe,0x7400deff,0x01ff6007,0x0fb9be60,0x7ec00302, - 0x027dc007,0x4fc827dc,0x3f203f70,0xfc8bf704,0xfc8bf704,0xfc8bf704, - 0xfc8bf704,0xf30bf704,0x07ffd9df,0x84faa7d4,0x07fc41fe,0x07f87f40, - 0xdf101fd0,0x07f80022,0x2000ff60,0x00fe65fa,0x001fec00,0x98103fe6, - 0x0ffcc1ff,0xff100fc8,0x440ffa87,0x07fd43ff,0xff50ffe2,0x543ff881, - 0x1ffc40ff,0x7dc03fea,0x5401dfff,0xfc89f54f,0xd00df705,0x6c01fe1f, - 0x006f883f,0xf5006f98,0x9fb0001f,0xa80006e8,0xfd8000ff,0xfc86fcdf, - 0x04ffecdf,0xdff701f6,0x2e07ffd9,0x3ffeceff,0xfd9dff70,0x3bfee07f, - 0xf703ffec,0x07ffd9df,0x5000cfec,0xfa93ea9f,0x013f600f,0x401fe1fd, - 0x37c41efb,0x013f6600,0x33007fea,0x2e07fdc4,0xf500505f,0x7e40003f, - 0xfd703fff,0x6e805dff,0xdfffea80,0x7fff5401,0x7ff5401d,0x7f5401df, - 0x75401dff,0x7c01dfff,0x54fa8005,0x00bfe29f,0x775c3fd1,0xddff0ffe, - 0x7fff409d,0x2600df12,0xf300effe,0xf7007fff,0x207fffdf,0x7fdcdffb, - 0x07ffff30,0x80022000,0x0017e001,0x00060003,0x0018000c,0x07220030, - 0x7d53ea00,0x26007fb4,0x3bbbae6f,0x9ddddb0e,0xd12ecb80,0x0f3a600b, - 0x0019bd30,0x073bbb22,0x17bdb730,0x00337a60,0x00000000,0x00000000, - 0x00000000,0x00000000,0x4d3ea9f5,0x00154004,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x20000000,0x009f54fa, - 0x77777400,0xeeeeeeee,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x4c000000,0x0007d33e,0x77777740,0x0eeeeeee, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x54400000,0x2a20001a,0x0154c01a,0x54400b20, - 0xaaa98000,0x99953100,0x032e0059,0x10053066,0x22004177,0x04c801aa, - 0x01aa8800,0x500d5440,0x51017997,0x51000035,0x0bb88035,0x00d54402, - 0x0007fea0,0xf500ffa2,0x3e6009ff,0x3fef9803,0xfffff700,0xffffb89f, - 0xf8804fff,0x3e0ff886,0x3ffe202f,0x5404ebcf,0x0fec01ff,0x07fd1000, - 0x103fe880,0x05fffffd,0x80007fea,0x7c403fe8,0x04ebcfff,0x88003ff5, - 0x3a2001fe,0x46fdc01f,0x7dc404fb,0x6baec00b,0xabcffd80,0x3fff24ec, - 0x804fb9df,0x41dd03fb,0x236600fd,0x800effc8,0x3e601fe8,0x3fd10005, - 0x01fe8800,0x008833f6,0x20007fa2,0xd9801fe8,0x00effc88,0x00007fa2, - 0x00000000,0x9fffffd5,0x036cf640,0x98407bee,0xf54fffff,0x001fd009, - 0x00020000,0x0007f400,0x44000000,0x0000007f,0x00200000,0x40153000, - 0xa802a62a,0x2a802a62,0x33fb7ff2,0x3bfa204d,0x007fe201,0x53fffff2, - 0x27d404fa,0x40015540,0x553002aa,0x50555555,0x01aa807f,0x554c1544, - 0xf82aaaaa,0x2aa8002f,0x802aa800,0x50aa02a9,0x55555555,0xf102fd81, - 0xf8817ecf,0x7c40bf67,0x1f61ff37,0x5c02aa80,0xfff9005f,0x013ea9ff, - 0xff8803fb,0x3fe2002f,0xfffc802f,0xdf07ffff,0x6406fb80,0xffffc85f, - 0xffb87fff,0x3ffe2003,0x3ffe2002,0x41ffe402,0x7fffc6f8,0x6c0fffff, - 0x6cff102f,0x6cff102f,0x2eff102f,0x4401ba5f,0x3f202fff,0xffff7003, - 0x8813ea9f,0xfffa805f,0x3ffea004,0xaacfc804,0x5f902aaa,0xf103ff80, - 0x559f901f,0xff985555,0xfa802eff,0x3ea004ff,0x7fe404ff,0x5546f886, - 0x0aaadfda,0x7f8817ec,0x3fc40bf6,0x5fe205fb,0x4017e7fa,0x3604fffa, - 0xfff3002f,0x813ea9ff,0xafd802fc,0x2bf6007f,0x03fc807f,0x2a02fc40, - 0x04fd80ff,0x3fa007f9,0x404ffd89,0x2007fafd,0x6407fafd,0x37c42fef, - 0xfd809f70,0x7ecff102,0x7ecff102,0x3e2ff102,0xb004faef,0x7f40ff5f, - 0x3fff2002,0x7c09f54f,0xfd7f8807,0x3aff1003,0x01fe401f,0x3a00fec0, - 0x807fcc4f,0x5f9803fc,0xf8827fd4,0xf1003fd7,0xfc807faf,0x037c46fb, - 0x2fd809f7,0x17ecff10,0x0bf67f88,0xffd33fc4,0x7f88019f,0x0bfa03fd, - 0x29ffd500,0x07f504fa,0x13ee9f50,0x27dd3ea0,0x2000ff20,0x7fcc04fa, - 0xfc80ff60,0x886f9803,0x74fa81ff,0x29f5009f,0x2bf204fb,0x81be22fd, - 0x17ec04fb,0x0bf67f88,0x05fb3fc4,0x3fae1fe2,0x53ea03ff,0x07fb04fb, - 0x4fa84c00,0xfb001fd0,0x3601fe65,0xc80ff32f,0x1fd0003f,0xdf34fd80, - 0xf003fc80,0xb07f905f,0x201fe65f,0x40ff32fd,0x226faafc,0x013ee06f, - 0x9fe205fb,0x4ff102fd,0x0ff102fd,0x417ff7ee,0x20ff32fd,0x500006fb, - 0x00bf309f,0x01fe8ff1,0x03fd1fe2,0x777777e4,0x01fdc04e,0x0bf63fe2, - 0xdddddf90,0x43ffa89d,0x23fc43fb,0x1fe201fe,0x4bf203fd,0x40df11fe, - 0x17ec04fb,0x0bf67f88,0x05fb3fc4,0x9be41fe2,0x23fc43ff,0x2ff881fe, - 0x84fa8000,0x5fa801fc,0xbf5027e4,0x3f204fc8,0x06ffffff,0x7e4037c4, - 0xffc806fe,0xa86fffff,0x0ff89eff,0x13f22fd4,0x27e45fa8,0x2bf52fc8, - 0x13ee06f8,0x3e205fb0,0x7c40bf67,0x7c40bf67,0x2fdcdb07,0x09f917ea, - 0x0620bff2,0x3e227d40,0x985fb006,0x30bf607f,0x01fe40ff,0x8803f900, - 0xfc801fff,0x7fec4003,0x42fd82ff,0x0bf607f9,0x8bf20ff3,0x206f89ff, - 0x17ec04fb,0x0bf67f88,0x05fb3fc4,0xb2f41fe2,0x4c2fd89f,0x3fff607f, - 0x5004fedd,0x802fb89f,0x99999ff8,0x9ff881ff,0x01ff9999,0x4c0007f9, - 0x05fb805f,0x20007f90,0xff886fe9,0x1ff99999,0x9999ff88,0x2fc81ff9, - 0x81be33ee,0x1fe404fb,0x0ff25fa8,0x07f92fd4,0x9f04d7ea,0x7c43ff71, - 0xff99999f,0x3fffaa01,0x7f9002ce,0xff5007e8,0x9fffffff,0xffffff50, - 0x3f209fff,0x07f40003,0x64013ee0,0x3a20003f,0x7fffd42f,0xa84fffff, - 0xffffffff,0x222fc84f,0x2e06f9ff,0x827dc04f,0x413ee4fc,0x413ee4fc, - 0xfdffb4fc,0xfa87ffff,0xffffffff,0x0077c404,0x9f517f40,0x3337f600, - 0xd86fdccc,0xdcccccdf,0x007f906f,0x5c04fa80,0x07f9004f,0x6c2fe800, - 0xdcccccdf,0xccdfd86f,0xc86fdccc,0x37e7e42f,0xf9809f70,0x30ffcc1f, - 0x1ff983ff,0xff307fe6,0x3fffb6a3,0xcdfd80ce,0x06fdcccc,0x37601fd4, - 0x6c6fd989,0x0ff8800f,0xff887fe0,0x3207fe00,0x7f80003f,0xc8027dc0, - 0x4c15003f,0x3fe20ffb,0xf887fe00,0x907fe00f,0x6fff885f,0x32013ee0, - 0x4ffecdff,0xfecdffc8,0xcdffc84f,0x3f704ffe,0xf007fc40,0x00fe403f, - 0xdfffffb1,0xa802fcc3,0x527ec05f,0x84fd80bf,0xeeeeeefc,0x80bee006, - 0xdf9004fb,0xf8dddddd,0x41ffffff,0x27ec05fa,0x4fd80bf5,0x7fe417e4, - 0x7ff776c6,0xfd700eee,0x75c05dff,0x2e02efff,0x202efffe,0x17ea00fc, - 0x14c09fb0,0x82cdba80,0x7fb001ca,0x3f66fa80,0x6437d403,0x7fffffff, - 0xb80f2200,0xfff9004f,0xcb8fffff,0x7fb02cdd,0x3f66fa80,0x3237d403, - 0x46ff882f,0xffffffff,0x8001800f,0x90018001,0x403fd80b,0x000006fa, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x0d544000,0x2600aa60,0x54c014c1,0x14c19802,0x400154c0, - 0xcb9802c9,0x0332e02c,0x30a60f22,0x00332a05,0x4000b260,0x0cca83cc, - 0x01e64000,0x2e200b26,0x6644020b,0x00cca801,0xe8803ca8,0x7ffd403f, - 0xf83fe204,0x3ffea02f,0xf83fe204,0x3ffea02f,0x3f7ee004,0x3ffff604, - 0x7f7ec0ef,0x220fe40f,0x05ff11ff,0xa8003bee,0x6c003fff,0x03bee05f, - 0x202fec00,0x2203fffa,0x4eacffff,0x9d95ff70,0x9003bee0,0x1fe880bf, - 0x7dc6fdc0,0xfd83ba04,0xf71bf700,0xfb077409,0x2e37ee01,0x2a7d004f, - 0x261bf907,0x54fea4fd,0x2213ea3f,0x807fa0ff,0xfa800ef9,0xb003fc8d, - 0x1df3007f,0x403fd800,0x03fc8dfa,0xdffb31d3,0xfffdb881,0x3be603ef, - 0x0017f200,0x00000000,0x00000000,0x7b8dd800,0x6f981ff0,0x8a7c47ee, - 0x020200ee,0x22002620,0x4c400cc1,0x00262000,0x18800988,0x011000cc, - 0x0ffb7fe2,0xf9004c40,0x5555550b,0xaa981555,0x982aaaaa,0x2aaaaaaa, - 0xaaaaaaa8,0x555540aa,0x200aaaaa,0x7cc002aa,0x86f882ff,0x44bee5fa, - 0x0005f94f,0x00000000,0x00000000,0x00000000,0x001ff982,0xff0bf900, - 0x1fffffff,0xffffffc8,0xffffc87f,0xfff87fff,0x40ffffff,0xffffffff, - 0x5fff100f,0x26013000,0x30ffd45f,0xf33fb3bf,0x9dfb7009,0xcefdb801, - 0x677edc00,0x677edc00,0xdfdb7100,0x3b6e203b,0xb7101def,0x2203bdfd, - 0x01defedb,0x01bffb2a,0x7039dfb7,0xfb5550bf,0xfc81555b,0x82aaaaac, - 0xaaaaacfc,0xdfdaaa82,0x55540aaa,0x00aaadfd,0x1009fff5,0x83bdfdb7, - 0x07bee5f9,0x7f4fffee,0x76f7ec00,0xbdfb02ff,0x3f605ffd,0xb02ffede, - 0x05ffdbdf,0xfffddff7,0xfddff705,0xdff705ff,0xf705fffd,0x05fffddf, - 0x5ffddffb,0xffdffd30,0x404fb87f,0x1fe404fb,0x0007f900,0xfb8013ee, - 0xff5fb004,0xfddff700,0x8afcc5ff,0x426200ff,0x27e402fc,0x9f903fea, - 0x7e40ffa8,0x3207fd44,0x207fd44f,0x43fdc419,0x43fdc419,0x43fdc419, - 0x23fdc419,0x1bea0dfc,0x3ff513fa,0x3ee027dc,0x001fe404,0x2e0007f9, - 0x13ee004f,0x0ff5fe20,0xff710660,0x07f8afcc,0xf1017e60,0xf88ff20d, - 0x7c47f906,0x7c47f906,0x4007f906,0x3fe000ff,0x003fe000,0x0df30ff8, - 0x05fa87fa,0x027dcbf9,0x7f9013ee,0x001fe400,0x2e004fb8,0x74fa804f, - 0x7fc0009f,0x27fcbf30,0x5400fe80,0x549f504f,0x549f504f,0x549f504f, - 0x009f504f,0xfb000fec,0x00fec003,0x0fee3fb0,0x05f927e4,0x04fb9be2, - 0x3f2027dc,0x00ff2003,0x70027dc0,0x25fb009f,0x360007f9,0x7ccbf31f, - 0x4bee00df,0x77dc1dec,0x5feeeeee,0x3bbbbbee,0x3bee5fee,0x5feeeeee, - 0x3bbbbbee,0xec985fee,0x981ffffe,0x1ffffeec,0xfffeec98,0xfeec981f, - 0x05fb1fff,0x01fe97ea,0x403fa9fe,0x77e404fb,0xc84eeeee,0x4eeeeeef, - 0x70027dc0,0x47f8809f,0x764c01fe,0xf31ffffe,0x80efe98b,0xffbfd5f8, - 0x77777e43,0x3f24eeee,0xeeeeeeee,0x3bbbbf24,0x3f24eeee,0xeeeeeeee, - 0x6677fdc4,0x7fdc1ffc,0x41ffccce,0xfccceffb,0x677fdc1f,0x3fb1ffcc, - 0x1fe97ea0,0x03fa9fe0,0x3f2027dc,0x86ffffff,0xfffffffc,0x0027dc06, - 0x5fa809f7,0xff7027e4,0x23ff999d,0x4fe885f9,0x33f98fe8,0x002fdc9f, - 0x7dc00bf7,0x017ee005,0xfd81ff88,0x3607fe21,0x207fe21f,0x07fe21fd, - 0x817e47f6,0x40bf64fb,0x007266f8,0x3fc809f7,0x000ff200,0xf70027dc, - 0x4c2fd809,0x03ff107f,0x417e63fb,0xb9fdc6f9,0xffa97e1f,0x01ff5000, - 0x4003fea0,0xf5000ffa,0xfa87fa0b,0x7d43fd05,0x7d43fd05,0x3ee3fd05, - 0x7e45fb05,0x000bf704,0x3fc809f7,0x000ff200,0xf70027dc,0x4cffc409, - 0xa81ff999,0x263fd05f,0x44df305f,0x7c4bea6f,0x80067f44,0xfd000cfe, - 0x33fa0019,0x446fa800,0x1bea1ffd,0x7d43ffb1,0x50ffec46,0x1ffd88df, - 0x7fa85ff1,0x3e60ffc4,0x700faa1f,0x03fc809f,0x4000ff20,0x3ee004fb, - 0x3fffea04,0xa84fffff,0x8ffec46f,0xfb9935f9,0xf10fec5f,0xf983fb7d, - 0x0eccbdff,0x65efffcc,0x7ffcc0ec,0x4c0eccbd,0xeccbdfff,0x373bfe20, - 0x3e21feff,0xfeffdcef,0x373bfe21,0x3e21feff,0xfeffdcef,0x3737fee1, - 0xdffb82ff,0x7fc3ffdc,0x2027dc07,0x3f2003fc,0x09f70003,0xfb027dc0, - 0xfb99999b,0xb9dff10d,0x3e63fdff,0x45dfff35,0xfffa83fa,0xffffb102, - 0xffb101df,0xb101dfff,0x01dfffff,0xdfffffb1,0xdfffe981,0x7f4c1fc8, - 0x41fc8dff,0xc8dfffe9,0x7fff4c1f,0x7541fc8d,0x2a01efff,0xc81efffe, - 0x027dc05f,0xfc800ff2,0x09f70003,0xf8827dc0,0x207fe00f,0xc8dfffe9, - 0x0002201f,0x02620008,0x20009880,0x26200098,0x40008800,0x00440008, - 0x06000220,0x40600600,0xeeffeeed,0x7777e40e,0xefc86eee,0xd86eeeee, - 0xeeeffeee,0x7ff776c0,0x0bf50eee,0x02204fd8,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0xffffff80,0x7fe40fff,0xc87fffff, - 0x7fffffff,0xfffffff8,0x7fffc0ff,0xfb0fffff,0x006fa807,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x40f32000,0xca814c29,0x055cc00c,0x203cc800,0x98014c29,0x0bb8802c, - 0x40044002,0x298003c8,0x0310014c,0x8000b260,0x157300cb,0x76c17a20, - 0x00f32000,0x32a0aa62,0x027d400c,0xf882fec0,0x205ff11f,0x3ee00efb, - 0x36001eff,0x47fe205f,0x7d402ff8,0x3fe203ff,0x204eacff,0x203ffffa, - 0x7c4006f8,0x005ff11f,0x3fea01f6,0x3fb0003f,0x4fffff98,0x1fd06f88, - 0x8817f600,0x706ffffb,0x7ff401df,0x80ff6000,0x07fa0ff8,0x5100ef98, - 0xb005ffd7,0x0ff8807f,0xdfa807fa,0x1d303fc8,0x201dffb3,0x2ffdcffa, - 0x8800df10,0x007fa0ff,0x37ea02fc,0xd8003fc8,0x26ffea1f,0x37c44feb, - 0xfd800fe8,0x37ffe603,0x3be602ac,0x400bf700,0x10100098,0x20013100, - 0x26200ffb,0x00202000,0x20019831,0x717ec008,0x01be20bf,0xb7004040, - 0x18807fff,0x7ec000cc,0xff10bfa1,0xfe837c41,0x1004c400,0x310007ff, - 0x00000001,0x20000000,0x000004fd,0x00000000,0x6f983fe0,0x0000df10, - 0xfeffe980,0x000001ff,0x17ea3fb0,0x0df127dc,0x200003fa,0x000003fc, - 0x05e88026,0x82f443d9,0x417a21ec,0x17ee01ec,0x00e77edc,0x80e77edc, - 0x03d905e8,0x8073bf6e,0x413ee2fe,0x7ddb36f8,0x3bfb6e20,0xf13fe81d, - 0x6dc03ffd,0x65401cef,0xf91ffdee,0x44dfd305,0x701fd06f,0x7c0bdddd, - 0x7775c007,0x407f305e,0x45fb06f8,0x45fb06f8,0x05fb06f8,0x3fa61fdc, - 0x303fffef,0x7fffdffd,0x3f60df10,0x7f7ff4c2,0x2df903ff,0xdf100ffa, - 0x0bffdff5,0xfffddff7,0x5f52fdc5,0xffd309f7,0xb107fffd,0x3fffdfff, - 0xfff707f6,0xfe837c4f,0x7ffffc80,0x2aa2bf30,0xffff9009,0x8813ea0f, - 0x445fb06f,0x445fb06f,0x205fb06f,0x27f40ff9,0x3fa07fea,0x220ffd44, - 0xe85fb06f,0x40ffd44f,0x01efeff8,0x4c33ffe2,0x220cc1ff,0xd8bf27fb, - 0x9fd0bf17,0x7e41ffa8,0xfe8ff42d,0xff3dfb10,0x0fe837c4,0xfa83fc40, - 0x2fffffee,0xfa83fc40,0x6c1be204,0x6c1be22f,0x6c1be22f,0x3fffe62f, - 0xfc82fd44,0xfc82fd45,0xfd837c45,0x7e417ea2,0x00bffb05,0x9f709ff1, - 0xfe87fc00,0x547f93e0,0x44bf905f,0x3e3fb07f,0xf0dff98f,0x303fe21f, - 0x7f8803ff,0x537bff70,0x7c403ff9,0x4409f507,0x445fb06f,0x445fb06f, - 0x4c5fb06f,0x05f902ef,0x05f91be2,0x0df11be2,0x02fc8bf6,0xefe88df1, - 0x88ff11ff,0x00bf307f,0x50fe8fec,0x3f23fc5f,0x7dcdf102,0x3fa3fb04, - 0x13fc3ffc,0x7ff445ff,0xb83fc401,0x40bf904f,0x09f507f8,0x2fd837c4, - 0x17ec1be2,0x8bf60df1,0x07fa04f9,0x00ff47f8,0xb06f88ff,0xf00ff45f, - 0xdfb4fd8f,0x6f88df31,0xd930df30,0x323ffffd,0x37c4fb2f,0x27f807fa, - 0x23fb03fc,0x7c41effd,0x337ffe27,0x202efbef,0x09f707f8,0x7f881be6, - 0x7c40bf50,0x7c45fb06,0x7c45fb06,0x7cc5fb06,0xf807fa04,0xff00ff47, - 0x5fb06f88,0x4ff00ff4,0x56ff47f8,0x9837c45f,0x677fdc6f,0x9f51ffcc, - 0x745fa97e,0xfd9fe01f,0x3f23fb02,0x225fa80d,0xb0dffeef,0x83fc409f, - 0x0ff105fa,0x5fb83fc4,0x7ec1be20,0x7ec1be22,0x7ec1be22,0xfd80b222, - 0xfd8df102,0xf88df102,0x7ec5fb06,0x7ccdf102,0x17fffc46,0x2fd41be2, - 0x3fb03ff1,0x44bf3fe2,0x817ec1fe,0x413f26f8,0x20df31fe,0x45be22fd, - 0x07f88000,0x17ea0ff1,0xbf707f88,0x7c40ff80,0x2207fc2f,0x207fc2ff, - 0x64002ff8,0xc8bf704f,0xf0bf704f,0x22ff881f,0x4bf704fc,0xfffa87f9, - 0xfc837c40,0x7f417ea3,0x373ffea1,0x04fc84ff,0x42fdcbf7,0x0ffa1ffb, - 0x06f88ff5,0xb03fc400,0x02fe889f,0x2fdc1fe2,0xfe88bfe0,0xd117fc2f, - 0x22ff85ff,0x3a62ffe8,0x307fe204,0x1ff883ff,0x7fc0ffcc,0x88bffa22, - 0x0ffcc1ff,0xffd50ffe,0xfa86f883,0x36237d46,0x7ffd41ff,0x3ff102ef, - 0x3e21ff98,0x87ffea1f,0xffdcdff9,0x00037c41,0xff981fe2,0x404fecbd, - 0x0bf707f8,0xefcdffb8,0x6ffdc2fd,0x5c2fdefc,0xfdefcdff,0xb803ff62, - 0x3ffdcdff,0xfb9bff70,0x37fee07f,0x5c2fdefc,0x3ffdcdff,0xffceffa8, - 0x3e20efef,0x1ffdccef,0x7ee77fc4,0x5fd41fef,0x9bff7001,0xffb07ffb, - 0x83f99fdb,0x81dfffd8,0xcc8006f8,0x1cccffcc,0x177ffec4,0xcffcccc8, - 0x00df71cc,0xf71bffd5,0x1bffd505,0xffd505f7,0x7dc5f71b,0xfffea806, - 0x7ff5401e,0x7f5401ef,0xa82fb8df,0x201efffe,0xd1dfffea,0xfffdb8bf, - 0xffd300de,0xd83f91bf,0xffea8007,0x3ff201ef,0x0c03f93e,0x20017a20, - 0xffffffff,0x3e00603f,0xffffffff,0x4400bd73,0x00044000,0x00020022, - 0x000c0006,0x00c00044,0x01000040,0x3c800440,0x2000c000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x55530000,0x53035555,0x54c00557, - 0xba9800aa,0x2aaaa60a,0x2a600aaa,0x0032e009,0x32205950,0x020bb883, - 0x3c881654,0x6440736e,0x09999953,0x80357510,0x209aca98,0x20aa00a9, - 0x2e014c29,0x0164c03f,0x1dd127dc,0x64c076c0,0xfffffc82,0x7ffe44ff, - 0x3ee03fff,0x904fffff,0x2bffffff,0xfffffffc,0xfffffb81,0x000fe80d, - 0x320bffd3,0x7fffc41f,0x3fa64eac,0x6c3f905f,0x1fc80ffd,0x40fffff9, - 0xefffffc8,0xfffffc81,0x440bf65f,0x88ffc47f,0x1ffe02ff,0x203fffa8, - 0x3f62fff8,0x3a0df504,0x567e40ff,0x5dc1aaaa,0x81ffdb9a,0xecabcffd, - 0x5e7ff444,0x55535dca,0xfd83fd55,0x0efc989c,0xea8007f4,0x84fa85fa, - 0xeffd98e9,0x217ebaa0,0x83fb04fa,0x266624fa,0x2fbf607f,0x360ffda9, - 0x3baabcef,0x3fc40bf6,0x1fe83fe2,0x7d413f60,0x3e03fc8d,0x41fea1ff, - 0x1ffd03fd,0x40001fc8,0x0f7dc4fe,0x8077ec08,0xf70ff400,0xfd17ea07, - 0x45f88001,0x11000ee8,0x3a22fc40,0x22ffe40e,0xff100ee8,0x3e03fe20, - 0x003ff32f,0x1fe205fb,0x20000404,0x9300cc18,0xf885fd05,0x9035100f, - 0xfb80003f,0x4007fe25,0x20000ffa,0x4cdf11fe,0x743f91bb,0x2fc4000f, - 0x80000bf2,0x417e45f8,0x3f23fda9,0x441fe202,0x2e5fb06f,0x05fb005f, - 0x80001fe2,0x00000098,0x5fa8bf70,0x003f9000,0x3ee2fc80,0x00ff6005, - 0x3ee3fd00,0x22ffff52,0x3603fa4f,0x265f884e,0x2a9d104f,0xbf101cfd, - 0xc99827cc,0x8809f34f,0x10bfa07f,0x007fd4ff,0x7f8817ec,0x02f7775c, - 0xeeb82fb8,0x440005ee,0x70bf60ff,0xf90bdddd,0xf3000335,0x001fe41d, - 0xe80003fd,0xdf11f91f,0x3fa5f823,0x44077ec0,0x4403fa5f,0xffeefcdf, - 0x3fa5f884,0x21dfff00,0x3fc400fe,0xf519ff50,0x177f447f,0x7c40bf60, - 0x3ffffe47,0xfc82fb80,0x80007fff,0x90ff13fd,0xf90fffff,0x205bffff, - 0xd85feee8,0x83fe002f,0x403cccc9,0x3eafb1fe,0x07f4fb03,0x90980bfb, - 0x7ffc405f,0x2603fea3,0x4cc05f90,0x2200bf20,0x7ffcc07f,0xffe981ff, - 0x02fd80be,0x3fc40ff1,0x2017e440,0xa80007f8,0x8809f76f,0xdccca87f, - 0xff982fff,0x3fa0cfff,0xa8ff1002,0x7406ffff,0x0beadd1f,0x361fd3ec, - 0x17e6005f,0xff07ff10,0x002fcc03,0x7c4017e6,0x7ffec407,0x3ffae03f, - 0x8817ec3f,0x81fe207f,0x403fffd9,0x2da807f8,0x07fa7fe0,0x6400ff10, - 0x6fd9807f,0x7c400bf6,0x37d4cc47,0x8bec7fa0,0x7f4dd04f,0x74005fd8, - 0x83fc400f,0x03fa02fd,0x2001fd00,0x3fa607f8,0x405ffc8c,0x3f65ffda, - 0x440ff102,0x273fa07f,0x03fc4009,0xfc80fffc,0x7f8806fd,0x007fe200, - 0x03fc97f4,0x7cc03fe0,0xfc8ff406,0x7c737fd0,0x01bf7fa5,0x33265f70, - 0xfd837c42,0xd915f702,0x997dc05b,0x0ff102cc,0x3fe617fc,0xb2ffa802, - 0x81fe205f,0x0bf307f8,0xe807f880,0xfff103ff,0x00ff1007,0xf9002fe8, - 0xe801bee7,0x80df303f,0x267f51fe,0x47f37ffd,0x002ffafe,0x27ff4bf1, - 0x17ec1be2,0xecfaafc4,0x3a5f881f,0x0ff104ff,0x2fe417e6,0x7f94fc80, - 0xf8817ea0,0x8009f707,0xff9807f8,0x401ff603,0x3e2007f8,0x23fd000f, - 0xf5002ff8,0x40df301f,0x11fa0ff9,0x1fd07ec1,0xfd005ff3,0x113eff21, - 0x20bf60df,0x17dc20fe,0xfbfc87f4,0x2e0ff104,0x00bf704f,0x827dcff2, - 0x1fe204fc,0x220037dc,0x03ff007f,0xf8801fec,0x09fb1007,0xff91bee0, - 0xefe83105,0x20bb7cc0,0x77d46fc8,0x7f43fc80,0x5c03ff50,0x9f39f33f, - 0x5fb06f88,0xfe883fb8,0xcf99fdc0,0x0ff104f9,0x3fa03fea,0x8ffcc013, - 0x7fcc1ff9,0x441fe201,0x3e2003ff,0x206fb807,0xf1000ffa,0xfb999b0f, - 0xb999b0bf,0xfd881fff,0x44feddff,0xecdeffe8,0xffbdfd6f,0x59df703f, - 0x1fd09fd7,0x7c40ffdc,0x3bfbbf66,0x7ec1be23,0x3e61be22,0xfb37c41e, - 0xf107dfdd,0x667ff40f,0x3bf66ffc,0x44ffedcd,0xffecdffc,0x703fc404, - 0x88013bff,0x3bfb207f,0x003ff500,0x7ff43fc4,0xfff02dff,0xea807dff, - 0x702cefff,0x25bffffd,0x00dfffeb,0x0b7fff66,0x3ff207f4,0xdd90fec0, - 0x37c47dfd,0x07f62fd8,0x6c357ff5,0x3fbbb21f,0xff99993e,0x7dc43999, - 0x2e0bffff,0x2dffffff,0x5dfffd70,0x3ff33320,0x7fd41ccc,0x666644ff, - 0x3e1cccff,0xffff983d,0xfcccc803,0x1331cccf,0x00026600,0x00cc0004, - 0x00100011,0x1dfb01fd,0x4f980fea,0x2fd837c4,0xfff707f5,0x980fea9f, - 0x3ffffe4f,0x3103ffff,0x00133001,0xffff8018,0x503fffff,0xffff87b9, - 0x003fffff,0x20019bd3,0xffffffff,0x0000003f,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x02ae6200, - 0xdddfd910,0xdd9501dd,0x0f223b9b,0x00014400,0x22179995,0x07ddb34e, - 0x23deedb8,0x0d4c02a8,0x55440055,0x4c40009a,0x551001ab,0x2aa35555, - 0xaaaaaaaa,0x5555530a,0x5554c555,0xaaaa8009,0x57510009,0x00aaa001, - 0xff5013ee,0xf101bfff,0xddffd9bf,0xfeeffd81,0x00df11ff,0x22001fe0, - 0x12fffffe,0xffdff5bf,0xddffd30b,0x103fe8ff,0x01fe21ff,0xffffffa8, - 0x7ffd401d,0x7e401eff,0xdf4fffff,0xdddddddd,0x3ffff21f,0x3ff67fff, - 0xf00dffff,0x07ffffff,0x1fffffe4,0x80bffe20,0xf702fff8,0x1dfd759f, - 0x27e43fd8,0x3fa06fe4,0x2000df11,0xdfd8007f,0x3fe21312,0x83ff30cf, - 0x26140dfe,0x23fd80ff,0x3ea007f8,0x3ffecbae,0x9339ff30,0xefef805f, - 0x021f1aaa,0x559f90f8,0x67ec5555,0x82ffecba,0xffecabff,0xa9adfd83, - 0x3fea03ff,0x0fffc04f,0x3a20ffc4,0x7c43fc3f,0x6c07fc47,0x000df11f, - 0x3fe001fe,0x213fe201,0x017f24fb,0x37cc4fd8,0x3bffffe2,0xb85fa81d, - 0x83fd80ff,0x2fdfd400,0x85dfd0f8,0xb007f90f,0x81ff705f,0x547fc87f, - 0x206f986f,0x4c07fafd,0x209f902c,0x21fe27fa,0x837dc7f8,0x00df11fd, - 0x3bffbba6,0xf301eeee,0x307f880d,0x000ff4bf,0x17f43ff1,0x3b733fe2, - 0x82fd43ff,0x00fe85fc,0x05f9fe80,0xf27dc41f,0x3600ff21,0xf8bfb02f, - 0x320ff887,0x105fb03f,0x0007faff,0x3fe01ff8,0xbf70bfa1,0x3fb04fc8, - 0x67ed5be2,0x7ffffcc1,0x302fffff,0x06f880bf,0x007fcdf3,0x2fd57ee0, - 0x7fd43fc4,0x7cc17ea1,0x98007f87,0x1f05f8cf,0x643e1f50,0x02fd803f, - 0x887f8ff3,0xb817ec7f,0xf74fa83f,0x03fc0009,0xcffa8bf6,0x7ec0ffda, - 0x3e23fb02,0x4ffeefce,0xf3001fe0,0x306f880b,0x001fe2df,0x407f57f4, - 0x49f907f8,0x03fe05fa,0x3f9000ff,0x203e0bf1,0x3f21f1f9,0x202fd803, - 0x321fe0ff,0xb81fec5f,0xf32fd84f,0x1be6000f,0x6ff47fb0,0xfc80dfff, - 0x3e23fd03,0x03fea4ff,0x7ffc03fc,0x7fffffff,0x27d41be2,0xf50001fd, - 0x1fe207ff,0xffeeb7d4,0xa8ffc1ee,0x2aaaaffa,0xeff8b7c0,0x4cc1f1ee, - 0x3f21f0fd,0x24eeeeee,0x87fe02fd,0xefecbbff,0x64077d40,0x3a3fc45f, - 0x6f98001f,0x4f99fe40,0x709f7002,0x0ffe23ff,0x03fc07fe,0x67fee664, - 0x1be24ccc,0x07f71fe4,0x881bf600,0x3ebf707f,0x742fffff,0xffffff1f, - 0x3ee01fff,0x3dddff13,0x06f7c43e,0x3ffff21f,0x0bf66fff,0x3ffe1fe8, - 0xfd00bfff,0x9fffb99f,0x27e45fa8,0x0ff30150,0x3df52fd8,0xa83fe200, - 0x0ff11fff,0x03fc0bf6,0xf1017e60,0x4c6fb88d,0x74040bff,0xeeeffeee, - 0x7f41fe21,0xff817ea3,0x333ff331,0x887f4033,0x3e21f05f,0x07f90f80, - 0x7fc05fb0,0x3f267fe1,0x3ffb200e,0x7ec3fccf,0xfe83fcc2,0x203fc40f, - 0xfffd11fe,0xfb05bfff,0x3fb9fd9f,0x17ec1be2,0x7cc007f8,0x677fc405, - 0xfc81fffc,0xe87ecdff,0xeeeffeee,0xf931fe21,0x882fd41f,0x003fc0ff, - 0x82fc4bf3,0x43e03a0f,0x2fd803fc,0x3fc1ff10,0x320013f2,0x267fe22f, - 0x441ff999,0x1ff82fff,0x7e41ff10,0x4fffeeed,0xfb3effc8,0x7ec1be23, - 0x9800ff02,0x7ffc405f,0x2e00dfff,0x405ffffe,0x3fe204fb,0x41efffee, - 0x0df705fa,0x7fe400ff,0x1f05ffff,0x7f90f804,0x2e05fb00,0x3e23fc6f, - 0x07f4000f,0xfffffff5,0x1dfb09ff,0x3ee09f90,0x7dc17ee5,0x23fb0207, - 0x05fb06f8,0xf98007fa,0x08b7c405,0x803be200,0x99dfc999,0x77fffc41, - 0x10bf503d,0x00ff07ff,0x3bbbbfe2,0x3ea1f05f,0x07f90f82,0xff105fb0, - 0x4fc87f85,0xfb0ff200,0xfb99999b,0xff88060d,0xfb07fd43,0x003fe205, - 0x06f88fec,0x13f605fb,0x4405f980,0x7f50006f,0xffffff80,0x1fe21fff, - 0x7545fa80,0x200ff06f,0x82fc43fb,0x1f03d30f,0x3f600ff2,0x7c2ffd42, - 0x400ff987,0x7fc46fd9,0x0007fe00,0x3fb3bfee,0xc837ec3f,0x47f6005f, - 0x05fb06f8,0x3733ffe6,0x880bf301,0x3f90006f,0xdfdaaa80,0x1fe20aaa, - 0xfeeffa80,0x7f6c0dff,0x3eeeeeef,0x9ff103fa,0x2003e599,0xddddf90f, - 0x777ecddd,0xff05fffe,0xddb13f60,0xfa819fff,0x0027ec05,0x1dfffea8, - 0xeeefff98,0x36000eff,0x360df11f,0x3ffaa02f,0x0bf301ff,0x30006f88, - 0x04fb8005,0xfa801fe2,0xf01cefff,0xffffffff,0x2217e69f,0xff5fffff, - 0xffffffff,0x3ffff21f,0x3ff67fff,0x3e01ceef,0x741ff307,0xfb01cdef, - 0x006fa807,0xeb880180,0x8002ceee,0x20df11ec,0x013002fd,0x74405f98, - 0x00000005,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0xaaaa8000,0xaaa98099,0x31aaaaaa,0x55555555,0x260aaa00, - 0x2055100a,0x2aa0d42a,0x0aaaaaaa,0x0aa60551,0x40335555,0x455302a9, - 0xaaaaaaa9,0x803551aa,0x02aa22a8,0x03530aa8,0x01551a88,0x0154c550, - 0x2aaaaa55,0x00aaaaaa,0x751002aa,0x80551015,0xfffffff8,0x3ffff20c, - 0xf95fffff,0x0fffffff,0xfb0fff70,0x7c1be205,0xfff0fe65,0x21ffffff, - 0x2ff886f8,0x3fffffe2,0x07fec0bf,0xfff737fc,0x2bffffff,0x2fe406fb, - 0x7fd413fa,0xf9807f50,0xfa809fb4,0x220fff26,0xffffff6f,0x501fffff, - 0x36203ffd,0x4c3fffff,0x57fc406f,0x2a5ffcba,0xdccccccc,0x555bf95f, - 0xff880555,0x102fd87f,0xfa93e0df,0x6fed5542,0x0df10aaa,0xaff887fd, - 0x6c5ffeba,0x3ffd43ff,0x99999993,0x81ffc9ff,0x7fcc0ff8,0xf517f441, - 0xf53f9809,0x323fc80f,0x56f886ff,0x55bfb555,0x7ff4c155,0x7bfd01ff, - 0x7cc3ff95,0x443fc406,0x3fd000ff,0x6c000ff2,0x2fd87fbf,0x9f10df10, - 0x9f700fdc,0x9fb1be20,0xff10ff10,0x3637f747,0xdf7007ee,0xfd80ffa8, - 0xfc8bf904,0x2a027cc5,0xf807fe3f,0x0bfbf21f,0x13ee0df1,0xff9dff98, - 0xbf905501,0x3e2037cc,0x3003fd07,0x001fe4df,0x43fc67d4,0x4df102fd, - 0xdaadfbaa,0x4fb81abf,0x2fdcdf10,0xbf907f88,0xf887e774,0xff8807dc, - 0x7cc4fe81,0x25ff100f,0x2fcc0ff9,0x4fd8bea0,0xbfc8df30,0xb837c46f, - 0xff0e404f,0x26f98003,0x3fc406f9,0x5fb007f8,0x22001fe4,0xd87f88ff, - 0x74df102f,0xffffffff,0x04fb85ff,0x03be6df1,0x6fa83fc4,0x7dcfe7ba, - 0x7ec00fd9,0x6c1ff304,0x47fd403f,0x45f883fe,0xfa8bee09,0xfc87f906, - 0x1be22fda,0x3e0027dc,0x37cc001f,0x7f880df3,0xf9804fc8,0x2001fe46, - 0xb0ff12fd,0x21be205f,0x701f61fb,0x23be209f,0x1fe201ff,0x3adf2fec, - 0x803f6dd6,0xa7ec06fa,0xdfb006f9,0xa9be20df,0xff07ee3f,0xfc81fd03, - 0x1be26faa,0x3e0027dc,0x2fdc001f,0xff880df3,0x002ffeee,0xcefc85fb, - 0xfa82cccc,0x3f61fe25,0xfeeeeeee,0x1ba0fc86,0x3e209f70,0x7c402fef, - 0x3e2ff887,0x367f5f95,0x03ff100f,0x2fd8ff88,0x03fff100,0x64df937c, - 0x2627ec1f,0xfd2fc86f,0x7dc1be23,0x00ffc004,0x7cc5fd10,0x7fffc406, - 0x4c02efff,0xffffc86f,0x0fe85fff,0x3ff61fe2,0x6fffffff,0x202fc7c8, - 0xfff104fb,0x9ff8805f,0x7c5ffdb9,0x321fff35,0x009fb01f,0x001bfbf2, - 0x37c01ffd,0x03f23fff,0x83fc8df5,0x22bf52fc,0x009f706f,0x36001ff8, - 0x2037cc5f,0x7fe447f8,0x320bf601,0x099999cf,0x1fe217e4,0x37c40bf6, - 0x7013e3ec,0x2bbe209f,0x3fe200ff,0x443fffff,0xfc97fa5f,0x2006fa81, - 0x2001fff8,0x3a05fffb,0x329f9f57,0x3a1ff80f,0x3e2fc80f,0xf706f89f, - 0x01ff8009,0xf981df90,0xc83fc406,0x20df305f,0xef9803fc,0x9ff99999, - 0x2205fb09,0xdffdd56f,0x20ddffdd,0x2df104fb,0xff100efb,0xf1013599, - 0x3f917dcb,0x4001ff88,0x3e6005fb,0xfd02ff9f,0x3edbe3f2,0x0df33fd8, - 0x8cfb8bf2,0x009f706f,0xfc801ff8,0x406f980e,0x0df507f8,0x1fe40ff6, - 0x7ffffdc0,0xb4ffffff,0x4dbe205f,0xfdccefcc,0x09f704cd,0x05fd9be2, - 0x3e600ff1,0x3617e405,0x4fb8004f,0x7dcffa00,0x5f8fd80f,0x2a0fb3f9, - 0x3207f76f,0x3e7fe22f,0x8009f706,0x77e401ff,0x880df300,0x309fb07f, - 0x01fe40ff,0x6666664c,0xfb2ccffc,0xf11be205,0x2e017d49,0x44df104f, - 0x07f883ff,0xfb809f30,0x0003bea2,0x7dc013ee,0x7e427f46,0xdd9f32fb, - 0x07f47fc0,0x67e42fc8,0x009f706f,0x3f201ff8,0x01be600e,0xffa88ff1, - 0x3203fd82,0x7c40003f,0xf102fd87,0x3ee4f88d,0x8827dc01,0x20ffcc6f, - 0x9f3007f8,0xff13fb80,0x13ee0003,0xf30bfe20,0x47efc83f,0x3f606eff, - 0x0bf206fc,0x2e0dfff1,0x0ffc004f,0x4c00efc8,0x77fc406f,0x983fffee, - 0x0ff200ff,0xb0ff1000,0x31be205f,0x6c07e47f,0xeeeffeee,0xff70df10, - 0xa803fc41,0xc9fdc04f,0xffffffff,0x013ee06f,0x37e417f6,0xff917fee, - 0x1fffd40b,0xff905f90,0xb013ee0d,0xdddffddd,0x3ffffe67,0xff36ffff, - 0x15dddddd,0x19dfffff,0xf900ff60,0x7f880007,0xdf102fd8,0x03f22fa8, - 0x3ffffffe,0x20df10ff,0x01fe26fd,0x3ee027d4,0xffffffb3,0x7dc0dfff, - 0x807fdc04,0x3fee4ff8,0x202ffcc2,0x3f200fff,0x706ff882,0xffff809f, - 0xf34fffff,0xffffffff,0x3ffffe6d,0x00003fff,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x80322000, - 0x8026200b,0x6c40001c,0xdb880000,0x2e01defe,0xe881cefd,0x6d43d905, - 0xdfd98cef,0x00054400,0x207bddb7,0x700cefdb,0xc83ddfdb,0x21bd505e, - 0xd52ed8bd,0xeeeed81b,0xaa986eee,0x2017540a,0x2e1d74e9,0x77441dfd, - 0x6c03b600,0x40df504f,0x7ff304fa,0x0ffe6000,0x7dc04fa8,0x42fffeef, - 0xfffeffe9,0xfd837c43,0x3bff7be2,0x7406fdef,0xffe9807f,0xefd87fee, - 0x7f42ffed,0x442feeef,0x17fc43ff,0xf3ffdb9f,0xfffe8bfd,0x7dc7ffff, - 0x3ea1ffff,0xfca7d404,0x1fffefc9,0x6fa81fec,0x32ebfe20,0x2a01ff9b, - 0x13fe604f,0x805ff700,0x20cc04fa,0x27f47fb8,0x6f887fea,0x36145fb0, - 0x405f90ff,0xdfe807fe,0x513f2140,0x417ee1ff,0x361ff980,0x5c77fc4f, - 0x200fd4ef,0xf70cc3fe,0x2e02fccb,0x45fdf93f,0x837d45fc,0x7fd403fd, - 0x403fffff,0x7f4404fa,0x1efc800d,0x0004fa80,0x82fd43fe,0x41be25fc, - 0x97ee02fd,0x072204fa,0xf100bf90,0x7e4ff20d,0xab7e4003,0xf52ff86f, - 0x32007ecf,0x37cc405f,0x9174cdf1,0x307ff23f,0x883ff0df,0x7fc400ff, - 0x402ffc9c,0xdfb004fa,0x03bf6201,0x00027d40,0x40bf23fb,0x41be26f8, - 0x8fea02fd,0xe80004f9,0x04fa801f,0x0bfee9f5,0x1ff9fd00,0xb27d4ff0, - 0x077d401f,0x37fff644,0x365fc9fe,0xd107f90f,0xfb89f90b,0x645fb804, - 0x7777645f,0x205eeeff,0x7f441ffb,0x5ccccc04,0x981999df,0x1ffffeec, - 0x13fc03fd,0x88bf60df,0xeeefeedb,0x266665fe,0x41999999,0xefb800ff, - 0x5feeeeee,0x0077fff6,0x7c0bffe2,0x0fd8fea7,0x3203ff30,0x746f99af, - 0x3f43ffa7,0xf88005f9,0x6c00ff47,0x363fcc2f,0xffffffff,0x8ffdc07f, - 0xff805ff8,0xffffffff,0x33bfee1f,0x3fd1ffcc,0x0df13fc0,0xcffe8bf6, - 0x2ccccefd,0x3ffffffe,0xff11ffff,0x3bbbf200,0x4c4eeeee,0x200efffd, - 0xff00ffe8,0x01fb1fd4,0x37c05fd1,0x98fd8df5,0x64df3fcf,0x2fd8002f, - 0x3f600df3,0x2a03fc42,0x3fe6004f,0x201ffd43,0xcefdcccc,0x3ff10ccc, - 0x0bf63fb0,0x0df137c4,0x52fd4bf6,0xcccc809f,0x0ccccccc,0x3ee003fe, - 0xfd510005,0x77f7ec0d,0x8fea7f80,0x04fd80fd,0x37ff6fec,0x3e3f27ee, - 0x017e4bf6,0x3fcafd40,0xf989fb00,0x8027d406,0xfd302ffb,0x027d4009, - 0x47fa0bf5,0x8bf704fc,0x97fc40ff,0x01bea2fc,0x01ff4000,0x00007fd4, - 0xdf701ff1,0xa9fe17f6,0xf703f63f,0x17b7100d,0x5ebfa877,0x7e49f5f9, - 0xd1ff0002,0x3bea001f,0xf500ff60,0x03df9009,0x800dfe88,0x1bea04fa, - 0x3e23ffb1,0x20ffcc1f,0x3ffa22ff,0x3fa27f72,0x0054001f,0x8102ffea, - 0x30000cfe,0x23ff30ff,0x53fc3ff8,0xf307ec7f,0x4c00001f,0xfbf32fdf, - 0x80017e47,0x2005fdfc,0xfffdfff8,0x1027d401,0x6c001dfb,0x27d400ef, - 0xfb9dff10,0x7fdc3fdf,0xb83ffdcd,0xfdefcdff,0x7dd9df12,0x403b99ff, - 0xffd806fd,0x7cc7ecdf,0x0eccbdff,0xffb999dd,0x4c3ff889,0xfa9fe1ff, - 0xfff83f63,0x32eeeeee,0x7ddddddd,0xff07ffc4,0x0017e45f,0x002fff98, - 0x37ffbbf6,0x8164c06f,0x70005fe8,0x27d403ff,0x37fffa60,0x7f541fc8, - 0x3aa01eff,0x22fb8dff,0xff90efeb,0x3ff403ff,0xffffea80,0xffffd885, - 0xffffb0ef,0x0bfb05df,0x53fc3ff2,0xff07ec7f,0x5fffffff,0x3bbbbba6, - 0x322ffc3e,0x00bf20ff,0x2006fe80,0x09fb06fb,0x001f4400,0x98807ea0, - 0x00011000,0x00088003,0x26002601,0x0088002c,0x4cc01310,0x00000009, - 0x00000000,0x00000000,0x4407ee00,0x3333264f,0x002ccccc,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x40000000, - 0x3fee0400,0x4fffffff,0x74400000,0x4039fb54,0x64400aa9,0xb9800001, - 0x000001bc,0x03372a00,0x4017bb93,0x16dc04c9,0x200e65c4,0x333100a8, - 0x81333333,0x4cc40bb9,0x09999999,0x26057700,0x257714c2,0x00000bb9, - 0x40000000,0xfeefcdf8,0x7fff444f,0x80be202f,0xc81d705c,0x40dfdcdf, - 0x3203645c,0xfd83320d,0x3f21ffff,0x6cc0ffff,0x3fe207ff,0x3fffea0f, - 0x41bf604f,0xfffffffa,0x0efb84ff,0x3ffffff2,0xfd802fff,0x11ff880d, - 0x54ffa3ff,0x000000ff,0x44000000,0x3fea3fff,0x3ee6ff60,0x8fc46a0f, - 0x717fa238,0x557641df,0x7ec5d88a,0x7d40ff23,0x1731be65,0x32049fb1, - 0x3f7fe23f,0x897ffc07,0x05fd10ff,0x5107fbf5,0x55555555,0x543be603, - 0xebbbbbbb,0x01fec02f,0xd1fe83fa,0x001fe67f,0x00000000,0x3e0ffe20, - 0xfc8bf31f,0x5cfd3fa3,0x57fa20ff,0x27e60efb,0x3f8afcfa,0x0fe83fa2, - 0x07fa0fe8,0x7ec0bf70,0x03fc45c2,0x1fd4bfea,0x75ba13ea,0x8800000f, - 0x05f90009,0x808004c4,0x3fccbf60,0x00000000,0x83fc4000,0xa87f52fd, - 0x77f7544f,0xefe880bf,0x6ab5c0ef,0xbf317299,0x8ff22fcc,0x7f4403fc, - 0x027ff542,0xff880ff1,0x4f987f70,0x44f98fdc,0x99999998,0x20000099, - 0x000002fc,0x37c4bf60,0x00000000,0x837c4000,0xb8bf32fd,0x1ffe883f, - 0x407ff440,0x21ddf54d,0x362fc86b,0x7ccdf12f,0x42ff4406,0x103ffdc9, - 0x25fc80ff,0x117e45f9,0x2a1fd8bf,0xffffffff,0x3200004f,0x0000002f, - 0x037c47f2,0x00000000,0xd837c400,0x223ff12f,0x37f220fe,0xf701dfdf, - 0x2ab90bff,0x88b90fae,0xd8df10ff,0x5407f62f,0x7f9804ff,0xd910ff10, - 0xbdfe81df,0x207e46fd,0x2eee66f8,0x02bbbbbb,0x00000000,0x00000000, - 0x00000000,0x17ec1be2,0x87ffdff7,0xfd33f2fe,0xfe8efb81,0xdb547d45, - 0x22fd89d4,0x137c42fd,0xbffb81df,0xff700999,0x3a61fe20,0xfffb102d, - 0xb827cc19,0x6d40003f,0x2ca8103d,0xffb80dcc,0x55534fff,0x00000555, - 0x00000000,0x7ec1be20,0x40e6e4c2,0x20c3f109,0xbfd10efb,0x99339dd8, - 0xf527dc1f,0xfb93ee0b,0x3ffffe25,0xffddb2ff,0xffffe85f,0x010001ff, - 0x00130062,0x2ffffdc0,0x7ffccbee,0x503fff11,0x3a799999,0x007fffff, - 0x00000000,0x0df10000,0x10000bf6,0x2077405f,0x3ba20fe8,0x741fda9b, - 0xfd007f46,0x999076c1,0x3ae39999,0xccb80bde,0x0000cccc,0x80000000, - 0x8dfd89fe,0xfff50fd8,0x00fffe65,0x333332e0,0x00000004,0x10000000, - 0x4cbf60df,0x3eeeeeee,0x04401510,0xdfb70088,0x00202019,0x00000101, - 0x00000000,0x7c400000,0x2ffffec5,0x1ffd1bfa,0x00000000,0x00000000, - 0x20df1000,0xdddd32fd,0x00007ddd,0x00000000,0x00000000,0x00000000, - 0x06a00000,0x80413bae,0x00000009,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, -}; - -static signed short stb__consolas_24_latin1_x[224]={ 0,5,3,0,1,0,0,5,3,3,1,0,2,3, -4,1,1,1,1,1,0,2,1,1,1,1,4,2,1,1,2,3,0,0,1,1,1,2,2,0,1,2,2,1, -2,0,1,0,1,0,1,1,1,1,0,0,0,0,1,4,1,3,1,0,0,1,1,1,1,1,0,1,1,2, -1,2,2,1,1,1,1,1,2,2,0,1,0,0,0,0,1,1,5,2,0,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,5,1,1,1,0, -5,1,0,0,2,1,1,3,1,0,2,1,2,3,0,1,1,4,5,2,2,1,0,0,0,2,0,0,0,0, -0,0,-1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0, -0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, - }; -static signed short stb__consolas_24_latin1_y[224]={ 17,0,0,1,-1,0,0,0,-1,-1,0,4,13,9, -13,0,1,1,1,1,1,1,1,1,1,1,5,5,4,7,4,0,0,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,20,0,5,0,5,0,5,0,5,0,0, -0,0,0,5,5,5,5,5,5,5,1,5,5,5,5,5,5,0,-3,0,8,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,17,5,-1,1,2,1, --3,0,0,1,1,5,9,9,0,1,0,2,0,0,0,5,0,8,17,0,1,5,0,0,0,5,-3,-3,-3,-3, --3,-4,1,1,-3,-3,-3,-3,-3,-3,-3,-3,1,-3,-3,-3,-3,-3,-3,5,-1,-3,-3,-3,-3,-3,1,0,0,0, -0,0,0,-1,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,2,0,0,0,0,0,0,0, - }; -static unsigned short stb__consolas_24_latin1_w[224]={ 0,4,8,13,11,13,14,3,8,7,11,13,7,8, -5,11,12,11,11,11,13,10,11,11,11,11,5,7,10,11,10,8,14,14,11,11,12,10,10,12,11,10,9,12, -10,13,11,13,11,14,12,11,12,11,14,13,13,14,11,6,11,7,11,14,8,11,11,11,11,11,13,12,11,10, -10,11,10,12,11,12,11,11,11,10,12,11,13,13,13,13,11,10,3,10,13,12,12,12,12,12,12,12,12,12, -12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,0,4,10,11,12,13, -3,11,11,14,9,11,11,8,11,10,9,11,9,8,12,12,11,5,3,9,9,11,13,13,13,8,14,14,14,14, -14,14,14,11,12,12,12,12,12,12,12,12,13,12,13,13,13,13,13,11,13,12,12,12,12,14,11,11,12,12, -12,12,12,12,13,11,12,12,12,12,12,12,12,12,11,12,13,13,13,13,13,13,12,12,12,12,12,13,11,13, - }; -static unsigned short stb__consolas_24_latin1_h[224]={ 0,18,6,16,21,18,18,6,23,23,11,13,9,3, -5,20,17,16,16,17,16,17,17,16,17,16,13,17,14,7,14,18,22,16,16,17,16,16,16,17,16,16,17,16, -16,16,16,17,16,21,16,17,16,17,16,16,16,16,16,22,20,22,9,2,6,13,18,13,18,13,17,17,17,17, -22,17,17,12,12,13,17,17,12,13,17,13,12,12,12,17,12,22,25,22,5,16,16,16,16,16,16,16,16,16, -16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,17,21,16,15,16, -25,20,6,17,12,11,6,3,11,5,9,15,10,10,6,17,20,5,4,10,12,11,17,17,17,17,20,20,20,20, -20,21,16,20,20,20,20,20,20,20,20,20,16,20,21,21,21,21,21,11,21,21,21,21,21,20,16,18,18,18, -18,18,18,19,13,16,18,18,18,18,17,17,17,17,18,17,18,18,18,18,18,13,18,18,18,18,18,22,22,22, - }; -static unsigned short stb__consolas_24_latin1_s[224]={ 252,250,247,62,40,106,104,252,17,9,70, -48,159,238,215,91,183,221,233,12,36,1,222,13,152,220,247,223,37,189,26, -40,100,232,1,24,194,183,25,36,50,76,49,87,245,112,196,1,100,129,207, -164,208,176,181,167,153,138,126,34,146,26,177,26,201,62,119,127,171,139,65, -15,40,245,89,74,141,176,48,74,79,28,225,151,52,87,237,211,162,231,189, -41,1,64,201,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170, -170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,252,247,157, -143,1,103,5,186,235,59,201,118,210,238,94,227,167,14,130,140,222,196,79, -221,252,149,60,106,86,113,127,201,198,213,66,118,103,52,155,67,133,173,14, -27,241,1,40,53,129,228,168,182,196,210,224,82,238,1,14,27,144,158,117, -94,172,185,198,211,131,81,99,91,133,159,146,120,234,209,210,188,224,100,236, -49,157,90,63,113,144,27,1,77,14,75,52,115, }; -static unsigned short stb__consolas_24_latin1_t[224]={ 13,49,156,125,27,49,70,1,1,1,156, -142,156,163,163,27,70,125,125,89,125,89,70,125,89,107,107,89,142,156,142, -70,1,107,125,89,107,107,125,89,125,125,89,125,125,125,125,107,125,1,107, -89,125,89,125,125,125,125,125,1,27,1,156,24,156,142,70,142,70,142,107, -107,107,89,1,89,89,142,156,142,107,107,142,142,107,142,142,142,142,89,142, -1,1,1,163,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, -107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,13,70,1, -107,142,107,1,27,156,89,142,156,156,163,156,163,156,142,156,156,156,70,27, -163,8,156,156,156,89,89,89,89,27,27,49,27,27,27,107,27,27,27,49, -49,27,49,49,49,107,27,1,1,1,1,1,156,1,27,27,27,1,27,107, -49,49,49,49,49,70,49,142,107,49,49,49,49,70,70,89,89,49,89,49, -70,70,70,70,142,70,70,70,70,70,1,1,1, }; -static unsigned short stb__consolas_24_latin1_a[224]={ 211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, -211,211,211,211,211,211,211,211, }; - -// Call this function with -// font: NULL or array length -// data: NULL or specified size -// height: STB_FONT_consolas_24_latin1_BITMAP_HEIGHT or STB_FONT_consolas_24_latin1_BITMAP_HEIGHT_POW2 -// return value: spacing between lines -static void stb_font_consolas_24_latin1(stb_fontchar font[STB_FONT_consolas_24_latin1_NUM_CHARS], - unsigned char data[STB_FONT_consolas_24_latin1_BITMAP_HEIGHT][STB_FONT_consolas_24_latin1_BITMAP_WIDTH], - int height) -{ - int i,j; - if (data != 0) { - unsigned int *bits = stb__consolas_24_latin1_pixels; - unsigned int bitpack = *bits++, numbits = 32; - for (i=0; i < STB_FONT_consolas_24_latin1_BITMAP_WIDTH*height; ++i) - data[0][i] = 0; // zero entire bitmap - for (j=1; j < STB_FONT_consolas_24_latin1_BITMAP_HEIGHT-1; ++j) { - for (i=1; i < STB_FONT_consolas_24_latin1_BITMAP_WIDTH-1; ++i) { - unsigned int value; - if (numbits==0) bitpack = *bits++, numbits=32; - value = bitpack & 1; - bitpack >>= 1, --numbits; - if (value) { - if (numbits < 3) bitpack = *bits++, numbits = 32; - data[j][i] = (bitpack & 7) * 0x20 + 0x1f; - bitpack >>= 3, numbits -= 3; - } else { - data[j][i] = 0; - } - } - } - } - - // build font description - if (font != 0) { - float recip_width = 1.0f / STB_FONT_consolas_24_latin1_BITMAP_WIDTH; - float recip_height = 1.0f / height; - for (i=0; i < STB_FONT_consolas_24_latin1_NUM_CHARS; ++i) { - // pad characters so they bilerp from empty space around each character - font[i].s0 = (stb__consolas_24_latin1_s[i]) * recip_width; - font[i].t0 = (stb__consolas_24_latin1_t[i]) * recip_height; - font[i].s1 = (stb__consolas_24_latin1_s[i] + stb__consolas_24_latin1_w[i]) * recip_width; - font[i].t1 = (stb__consolas_24_latin1_t[i] + stb__consolas_24_latin1_h[i]) * recip_height; - font[i].x0 = stb__consolas_24_latin1_x[i]; - font[i].y0 = stb__consolas_24_latin1_y[i]; - font[i].x1 = stb__consolas_24_latin1_x[i] + stb__consolas_24_latin1_w[i]; - font[i].y1 = stb__consolas_24_latin1_y[i] + stb__consolas_24_latin1_h[i]; - font[i].advance_int = (stb__consolas_24_latin1_a[i]+8)>>4; - font[i].s0f = (stb__consolas_24_latin1_s[i] - 0.5f) * recip_width; - font[i].t0f = (stb__consolas_24_latin1_t[i] - 0.5f) * recip_height; - font[i].s1f = (stb__consolas_24_latin1_s[i] + stb__consolas_24_latin1_w[i] + 0.5f) * recip_width; - font[i].t1f = (stb__consolas_24_latin1_t[i] + stb__consolas_24_latin1_h[i] + 0.5f) * recip_height; - font[i].x0f = stb__consolas_24_latin1_x[i] - 0.5f; - font[i].y0f = stb__consolas_24_latin1_y[i] - 0.5f; - font[i].x1f = stb__consolas_24_latin1_x[i] + stb__consolas_24_latin1_w[i] + 0.5f; - font[i].y1f = stb__consolas_24_latin1_y[i] + stb__consolas_24_latin1_h[i] + 0.5f; - font[i].advance = stb__consolas_24_latin1_a[i]/16.0f; - } - } -} - -#ifndef STB_SOMEFONT_CREATE -#define STB_SOMEFONT_CREATE stb_font_consolas_24_latin1 -#define STB_SOMEFONT_BITMAP_WIDTH STB_FONT_consolas_24_latin1_BITMAP_WIDTH -#define STB_SOMEFONT_BITMAP_HEIGHT STB_FONT_consolas_24_latin1_BITMAP_HEIGHT -#define STB_SOMEFONT_BITMAP_HEIGHT_POW2 STB_FONT_consolas_24_latin1_BITMAP_HEIGHT_POW2 -#define STB_SOMEFONT_FIRST_CHAR STB_FONT_consolas_24_latin1_FIRST_CHAR -#define STB_SOMEFONT_NUM_CHARS STB_FONT_consolas_24_latin1_NUM_CHARS -#define STB_SOMEFONT_LINE_SPACING STB_FONT_consolas_24_latin1_LINE_SPACING -#endif - diff --git a/images/androidlogo.png b/images/androidlogo.png deleted file mode 100644 index 40bf934b..00000000 Binary files a/images/androidlogo.png and /dev/null differ diff --git a/images/applelogo.png b/images/applelogo.png deleted file mode 100644 index 31f83b04..00000000 Binary files a/images/applelogo.png and /dev/null differ diff --git a/images/linuxlogo.png b/images/linuxlogo.png deleted file mode 100644 index bdc5b1d7..00000000 Binary files a/images/linuxlogo.png and /dev/null differ diff --git a/images/vulkanlogo.png b/images/vulkanlogo.png deleted file mode 100644 index 09bbb868..00000000 Binary files a/images/vulkanlogo.png and /dev/null differ diff --git a/images/vulkanlogoscene.png b/images/vulkanlogoscene.png deleted file mode 100644 index c44bba44..00000000 Binary files a/images/vulkanlogoscene.png and /dev/null differ diff --git a/images/windowslogo.png b/images/windowslogo.png deleted file mode 100644 index ecbbd20d..00000000 Binary files a/images/windowslogo.png and /dev/null differ diff --git a/imgui.ini b/imgui.ini new file mode 100644 index 00000000..a4fb8de6 --- /dev/null +++ b/imgui.ini @@ -0,0 +1,35 @@ +[Window][Debug##Default] +Pos=20,20 +Size=300,300 +Collapsed=0 + +[Window][Scene Hierarchy] +Pos=20,360 +Size=300,400 +Collapsed=0 + +[Window][Asset Browser] +Pos=20,780 +Size=600,220 +Collapsed=0 + +[Window][Console] +Pos=640,780 +Size=840,200 +Collapsed=0 + +[Window][Inspector] +Pos=2626,255 +Size=300,700 +Collapsed=0 + +[Window][Viewport] +Pos=660,350 +Size=316,350 +Collapsed=0 + +[Window][Debug Info] +Pos=20,20 +Size=300,300 +Collapsed=0 + diff --git a/screenshots/bloom.jpg b/screenshots/bloom.jpg deleted file mode 100644 index ff2a3439..00000000 Binary files a/screenshots/bloom.jpg and /dev/null differ diff --git a/screenshots/bufferdeviceaddress.jpg b/screenshots/bufferdeviceaddress.jpg deleted file mode 100644 index 0f146689..00000000 Binary files a/screenshots/bufferdeviceaddress.jpg and /dev/null differ diff --git a/screenshots/computecloth.jpg b/screenshots/computecloth.jpg deleted file mode 100644 index 6a15960c..00000000 Binary files a/screenshots/computecloth.jpg and /dev/null differ diff --git a/screenshots/computecullandlod.jpg b/screenshots/computecullandlod.jpg deleted file mode 100644 index 43ccfd7f..00000000 Binary files a/screenshots/computecullandlod.jpg and /dev/null differ diff --git a/screenshots/computenbody.jpg b/screenshots/computenbody.jpg deleted file mode 100644 index d238b6d8..00000000 Binary files a/screenshots/computenbody.jpg and /dev/null differ diff --git a/screenshots/computeparticles.jpg b/screenshots/computeparticles.jpg deleted file mode 100644 index 51b4330c..00000000 Binary files a/screenshots/computeparticles.jpg and /dev/null differ diff --git a/screenshots/computeraytracing.jpg b/screenshots/computeraytracing.jpg deleted file mode 100644 index a8ae3168..00000000 Binary files a/screenshots/computeraytracing.jpg and /dev/null differ diff --git a/screenshots/computeshader.jpg b/screenshots/computeshader.jpg deleted file mode 100644 index f9b28649..00000000 Binary files a/screenshots/computeshader.jpg and /dev/null differ diff --git a/screenshots/conditionalrender.jpg b/screenshots/conditionalrender.jpg deleted file mode 100644 index 1c38d79e..00000000 Binary files a/screenshots/conditionalrender.jpg and /dev/null differ diff --git a/screenshots/conservativeraster.jpg b/screenshots/conservativeraster.jpg deleted file mode 100644 index c2ae34ff..00000000 Binary files a/screenshots/conservativeraster.jpg and /dev/null differ diff --git a/screenshots/debugprintf.jpg b/screenshots/debugprintf.jpg deleted file mode 100644 index 7c017c32..00000000 Binary files a/screenshots/debugprintf.jpg and /dev/null differ diff --git a/screenshots/debugutils.jpg b/screenshots/debugutils.jpg deleted file mode 100644 index c2dcb609..00000000 Binary files a/screenshots/debugutils.jpg and /dev/null differ diff --git a/screenshots/deferred.jpg b/screenshots/deferred.jpg deleted file mode 100644 index aabcaa33..00000000 Binary files a/screenshots/deferred.jpg and /dev/null differ diff --git a/screenshots/deferredmultisampling.jpg b/screenshots/deferredmultisampling.jpg deleted file mode 100644 index 08721dfa..00000000 Binary files a/screenshots/deferredmultisampling.jpg and /dev/null differ diff --git a/screenshots/deferredshadows.jpg b/screenshots/deferredshadows.jpg deleted file mode 100644 index b302be64..00000000 Binary files a/screenshots/deferredshadows.jpg and /dev/null differ diff --git a/screenshots/descriptorbuffer.jpg b/screenshots/descriptorbuffer.jpg deleted file mode 100644 index fc1371d8..00000000 Binary files a/screenshots/descriptorbuffer.jpg and /dev/null differ diff --git a/screenshots/descriptorindexing.jpg b/screenshots/descriptorindexing.jpg deleted file mode 100644 index 270d4002..00000000 Binary files a/screenshots/descriptorindexing.jpg and /dev/null differ diff --git a/screenshots/descriptorsets.jpg b/screenshots/descriptorsets.jpg deleted file mode 100644 index 6ef3269c..00000000 Binary files a/screenshots/descriptorsets.jpg and /dev/null differ diff --git a/screenshots/displacement.jpg b/screenshots/displacement.jpg deleted file mode 100644 index 027986f7..00000000 Binary files a/screenshots/displacement.jpg and /dev/null differ diff --git a/screenshots/distancefieldfonts.jpg b/screenshots/distancefieldfonts.jpg deleted file mode 100644 index 902f6dcc..00000000 Binary files a/screenshots/distancefieldfonts.jpg and /dev/null differ diff --git a/screenshots/dynamicrendering.jpg b/screenshots/dynamicrendering.jpg deleted file mode 100644 index 86eca787..00000000 Binary files a/screenshots/dynamicrendering.jpg and /dev/null differ diff --git a/screenshots/dynamicrenderingmultisampling.jpg b/screenshots/dynamicrenderingmultisampling.jpg deleted file mode 100644 index d433ad17..00000000 Binary files a/screenshots/dynamicrenderingmultisampling.jpg and /dev/null differ diff --git a/screenshots/dynamicstate.jpg b/screenshots/dynamicstate.jpg deleted file mode 100644 index f2f773b8..00000000 Binary files a/screenshots/dynamicstate.jpg and /dev/null differ diff --git a/screenshots/dynamicuniformbuffer.jpg b/screenshots/dynamicuniformbuffer.jpg deleted file mode 100644 index 0fbb0deb..00000000 Binary files a/screenshots/dynamicuniformbuffer.jpg and /dev/null differ diff --git a/screenshots/ext_debugmarker.jpg b/screenshots/ext_debugmarker.jpg deleted file mode 100644 index c5b61b2a..00000000 Binary files a/screenshots/ext_debugmarker.jpg and /dev/null differ diff --git a/screenshots/gears.jpg b/screenshots/gears.jpg deleted file mode 100644 index 0b6a0177..00000000 Binary files a/screenshots/gears.jpg and /dev/null differ diff --git a/screenshots/geometryshader.jpg b/screenshots/geometryshader.jpg deleted file mode 100644 index ba1d0cd2..00000000 Binary files a/screenshots/geometryshader.jpg and /dev/null differ diff --git a/screenshots/gltfloading.jpg b/screenshots/gltfloading.jpg deleted file mode 100644 index 3e9bc42f..00000000 Binary files a/screenshots/gltfloading.jpg and /dev/null differ diff --git a/screenshots/gltfscenerendering.jpg b/screenshots/gltfscenerendering.jpg deleted file mode 100644 index 56702ec9..00000000 Binary files a/screenshots/gltfscenerendering.jpg and /dev/null differ diff --git a/screenshots/gltfskinning.jpg b/screenshots/gltfskinning.jpg deleted file mode 100644 index 9872cb46..00000000 Binary files a/screenshots/gltfskinning.jpg and /dev/null differ diff --git a/screenshots/graphicspipelinelibrary.jpg b/screenshots/graphicspipelinelibrary.jpg deleted file mode 100644 index 22fac75c..00000000 Binary files a/screenshots/graphicspipelinelibrary.jpg and /dev/null differ diff --git a/screenshots/hdr.jpg b/screenshots/hdr.jpg deleted file mode 100644 index 6398271e..00000000 Binary files a/screenshots/hdr.jpg and /dev/null differ diff --git a/screenshots/hostimagecopy.jpg b/screenshots/hostimagecopy.jpg deleted file mode 100644 index e73201c4..00000000 Binary files a/screenshots/hostimagecopy.jpg and /dev/null differ diff --git a/screenshots/imgui.jpg b/screenshots/imgui.jpg deleted file mode 100644 index 0e4c1ff9..00000000 Binary files a/screenshots/imgui.jpg and /dev/null differ diff --git a/screenshots/indirectdraw.jpg b/screenshots/indirectdraw.jpg deleted file mode 100644 index cd55748a..00000000 Binary files a/screenshots/indirectdraw.jpg and /dev/null differ diff --git a/screenshots/inlineuniformblocks.jpg b/screenshots/inlineuniformblocks.jpg deleted file mode 100644 index 29af8463..00000000 Binary files a/screenshots/inlineuniformblocks.jpg and /dev/null differ diff --git a/screenshots/inputattachments.jpg b/screenshots/inputattachments.jpg deleted file mode 100644 index 46f5f0d8..00000000 Binary files a/screenshots/inputattachments.jpg and /dev/null differ diff --git a/screenshots/instancing.jpg b/screenshots/instancing.jpg deleted file mode 100644 index 6b44fd63..00000000 Binary files a/screenshots/instancing.jpg and /dev/null differ diff --git a/screenshots/meshshader.jpg b/screenshots/meshshader.jpg deleted file mode 100644 index b78267d1..00000000 Binary files a/screenshots/meshshader.jpg and /dev/null differ diff --git a/screenshots/multisampling.jpg b/screenshots/multisampling.jpg deleted file mode 100644 index 085bec39..00000000 Binary files a/screenshots/multisampling.jpg and /dev/null differ diff --git a/screenshots/multithreading.jpg b/screenshots/multithreading.jpg deleted file mode 100644 index 80e47796..00000000 Binary files a/screenshots/multithreading.jpg and /dev/null differ diff --git a/screenshots/multiview.jpg b/screenshots/multiview.jpg deleted file mode 100644 index 5f5463d0..00000000 Binary files a/screenshots/multiview.jpg and /dev/null differ diff --git a/screenshots/negativeviewportheight.jpg b/screenshots/negativeviewportheight.jpg deleted file mode 100644 index afe7a4d0..00000000 Binary files a/screenshots/negativeviewportheight.jpg and /dev/null differ diff --git a/screenshots/occlusionquery.jpg b/screenshots/occlusionquery.jpg deleted file mode 100644 index 4aae51a7..00000000 Binary files a/screenshots/occlusionquery.jpg and /dev/null differ diff --git a/screenshots/offscreen.jpg b/screenshots/offscreen.jpg deleted file mode 100644 index 61f4e41b..00000000 Binary files a/screenshots/offscreen.jpg and /dev/null differ diff --git a/screenshots/oit.jpg b/screenshots/oit.jpg deleted file mode 100644 index 24d10ac2..00000000 Binary files a/screenshots/oit.jpg and /dev/null differ diff --git a/screenshots/parallaxmapping.jpg b/screenshots/parallaxmapping.jpg deleted file mode 100644 index fe4d9f06..00000000 Binary files a/screenshots/parallaxmapping.jpg and /dev/null differ diff --git a/screenshots/particlesystem.jpg b/screenshots/particlesystem.jpg deleted file mode 100644 index 18caaee5..00000000 Binary files a/screenshots/particlesystem.jpg and /dev/null differ diff --git a/screenshots/pbrbasic.jpg b/screenshots/pbrbasic.jpg deleted file mode 100644 index 33609bd2..00000000 Binary files a/screenshots/pbrbasic.jpg and /dev/null differ diff --git a/screenshots/pbribl.jpg b/screenshots/pbribl.jpg deleted file mode 100644 index 8920bf67..00000000 Binary files a/screenshots/pbribl.jpg and /dev/null differ diff --git a/screenshots/pbrtexture.jpg b/screenshots/pbrtexture.jpg deleted file mode 100644 index 36921d72..00000000 Binary files a/screenshots/pbrtexture.jpg and /dev/null differ diff --git a/screenshots/pipelines.jpg b/screenshots/pipelines.jpg deleted file mode 100644 index 607b8259..00000000 Binary files a/screenshots/pipelines.jpg and /dev/null differ diff --git a/screenshots/pipelinestatistics.jpg b/screenshots/pipelinestatistics.jpg deleted file mode 100644 index 5b9802c4..00000000 Binary files a/screenshots/pipelinestatistics.jpg and /dev/null differ diff --git a/screenshots/pushconstants.jpg b/screenshots/pushconstants.jpg deleted file mode 100644 index 77f5b11b..00000000 Binary files a/screenshots/pushconstants.jpg and /dev/null differ diff --git a/screenshots/pushdescriptors.jpg b/screenshots/pushdescriptors.jpg deleted file mode 100644 index b47f784e..00000000 Binary files a/screenshots/pushdescriptors.jpg and /dev/null differ diff --git a/screenshots/radialblur.jpg b/screenshots/radialblur.jpg deleted file mode 100644 index af137e88..00000000 Binary files a/screenshots/radialblur.jpg and /dev/null differ diff --git a/screenshots/rayquery.jpg b/screenshots/rayquery.jpg deleted file mode 100644 index 4030328f..00000000 Binary files a/screenshots/rayquery.jpg and /dev/null differ diff --git a/screenshots/raytracingbasic.jpg b/screenshots/raytracingbasic.jpg deleted file mode 100644 index 3e2b4470..00000000 Binary files a/screenshots/raytracingbasic.jpg and /dev/null differ diff --git a/screenshots/raytracingcallable.jpg b/screenshots/raytracingcallable.jpg deleted file mode 100644 index 13ac4de0..00000000 Binary files a/screenshots/raytracingcallable.jpg and /dev/null differ diff --git a/screenshots/raytracinggltf.jpg b/screenshots/raytracinggltf.jpg deleted file mode 100644 index d05aa348..00000000 Binary files a/screenshots/raytracinggltf.jpg and /dev/null differ diff --git a/screenshots/raytracingintersection.jpg b/screenshots/raytracingintersection.jpg deleted file mode 100644 index 62558750..00000000 Binary files a/screenshots/raytracingintersection.jpg and /dev/null differ diff --git a/screenshots/raytracingpositionfetch.jpg b/screenshots/raytracingpositionfetch.jpg deleted file mode 100644 index 54f1601d..00000000 Binary files a/screenshots/raytracingpositionfetch.jpg and /dev/null differ diff --git a/screenshots/raytracingreflections.jpg b/screenshots/raytracingreflections.jpg deleted file mode 100644 index f93b9428..00000000 Binary files a/screenshots/raytracingreflections.jpg and /dev/null differ diff --git a/screenshots/raytracingsbtdata.jpg b/screenshots/raytracingsbtdata.jpg deleted file mode 100644 index 3165f6be..00000000 Binary files a/screenshots/raytracingsbtdata.jpg and /dev/null differ diff --git a/screenshots/raytracingshadows.jpg b/screenshots/raytracingshadows.jpg deleted file mode 100644 index cfdf6cdf..00000000 Binary files a/screenshots/raytracingshadows.jpg and /dev/null differ diff --git a/screenshots/raytracingtextures.jpg b/screenshots/raytracingtextures.jpg deleted file mode 100644 index 47bf8cdf..00000000 Binary files a/screenshots/raytracingtextures.jpg and /dev/null differ diff --git a/screenshots/screenshot.jpg b/screenshots/screenshot.jpg deleted file mode 100644 index fb6cce7e..00000000 Binary files a/screenshots/screenshot.jpg and /dev/null differ diff --git a/screenshots/shaderobjects.jpg b/screenshots/shaderobjects.jpg deleted file mode 100644 index cce3938b..00000000 Binary files a/screenshots/shaderobjects.jpg and /dev/null differ diff --git a/screenshots/shadowmapping.jpg b/screenshots/shadowmapping.jpg deleted file mode 100644 index 6ccafadc..00000000 Binary files a/screenshots/shadowmapping.jpg and /dev/null differ diff --git a/screenshots/shadowmappingcascade.jpg b/screenshots/shadowmappingcascade.jpg deleted file mode 100644 index d2ac5ba7..00000000 Binary files a/screenshots/shadowmappingcascade.jpg and /dev/null differ diff --git a/screenshots/shadowmappingomni.jpg b/screenshots/shadowmappingomni.jpg deleted file mode 100644 index 51ccad5c..00000000 Binary files a/screenshots/shadowmappingomni.jpg and /dev/null differ diff --git a/screenshots/specializationconstants.jpg b/screenshots/specializationconstants.jpg deleted file mode 100644 index 9439c028..00000000 Binary files a/screenshots/specializationconstants.jpg and /dev/null differ diff --git a/screenshots/sphericalenvmapping.jpg b/screenshots/sphericalenvmapping.jpg deleted file mode 100644 index 511368a3..00000000 Binary files a/screenshots/sphericalenvmapping.jpg and /dev/null differ diff --git a/screenshots/ssao.jpg b/screenshots/ssao.jpg deleted file mode 100644 index 1f1e1eb7..00000000 Binary files a/screenshots/ssao.jpg and /dev/null differ diff --git a/screenshots/stencilbuffer.jpg b/screenshots/stencilbuffer.jpg deleted file mode 100644 index 16a5f103..00000000 Binary files a/screenshots/stencilbuffer.jpg and /dev/null differ diff --git a/screenshots/subpasses.jpg b/screenshots/subpasses.jpg deleted file mode 100644 index 2110fc33..00000000 Binary files a/screenshots/subpasses.jpg and /dev/null differ diff --git a/screenshots/terraintessellation.jpg b/screenshots/terraintessellation.jpg deleted file mode 100644 index b16ca2ac..00000000 Binary files a/screenshots/terraintessellation.jpg and /dev/null differ diff --git a/screenshots/tessellation.jpg b/screenshots/tessellation.jpg deleted file mode 100644 index f82397e5..00000000 Binary files a/screenshots/tessellation.jpg and /dev/null differ diff --git a/screenshots/textoverlay.jpg b/screenshots/textoverlay.jpg deleted file mode 100644 index 3795a82c..00000000 Binary files a/screenshots/textoverlay.jpg and /dev/null differ diff --git a/screenshots/texture.jpg b/screenshots/texture.jpg deleted file mode 100644 index cf53e16b..00000000 Binary files a/screenshots/texture.jpg and /dev/null differ diff --git a/screenshots/texture3d.jpg b/screenshots/texture3d.jpg deleted file mode 100644 index 61845bd3..00000000 Binary files a/screenshots/texture3d.jpg and /dev/null differ diff --git a/screenshots/texturearray.jpg b/screenshots/texturearray.jpg deleted file mode 100644 index b3a89af2..00000000 Binary files a/screenshots/texturearray.jpg and /dev/null differ diff --git a/screenshots/texturecubemap.jpg b/screenshots/texturecubemap.jpg deleted file mode 100644 index cb518575..00000000 Binary files a/screenshots/texturecubemap.jpg and /dev/null differ diff --git a/screenshots/texturecubemaparray.jpg b/screenshots/texturecubemaparray.jpg deleted file mode 100644 index f20b56ec..00000000 Binary files a/screenshots/texturecubemaparray.jpg and /dev/null differ diff --git a/screenshots/texturemipmapgen.jpg b/screenshots/texturemipmapgen.jpg deleted file mode 100644 index df61a56b..00000000 Binary files a/screenshots/texturemipmapgen.jpg and /dev/null differ diff --git a/screenshots/texturesparseresidency.jpg b/screenshots/texturesparseresidency.jpg deleted file mode 100644 index e4765188..00000000 Binary files a/screenshots/texturesparseresidency.jpg and /dev/null differ diff --git a/screenshots/timelinesemaphore.jpg b/screenshots/timelinesemaphore.jpg deleted file mode 100644 index 036b9999..00000000 Binary files a/screenshots/timelinesemaphore.jpg and /dev/null differ diff --git a/screenshots/triangle.jpg b/screenshots/triangle.jpg deleted file mode 100644 index 18c5d128..00000000 Binary files a/screenshots/triangle.jpg and /dev/null differ diff --git a/screenshots/trianglevulkan13.jpg b/screenshots/trianglevulkan13.jpg deleted file mode 100644 index 3e2b4470..00000000 Binary files a/screenshots/trianglevulkan13.jpg and /dev/null differ diff --git a/screenshots/variablerateshading.jpg b/screenshots/variablerateshading.jpg deleted file mode 100644 index 4d395bcb..00000000 Binary files a/screenshots/variablerateshading.jpg and /dev/null differ diff --git a/screenshots/vertexattributes.jpg b/screenshots/vertexattributes.jpg deleted file mode 100644 index 185968bf..00000000 Binary files a/screenshots/vertexattributes.jpg and /dev/null differ diff --git a/screenshots/viewportarray.jpg b/screenshots/viewportarray.jpg deleted file mode 100644 index 23f0efcf..00000000 Binary files a/screenshots/viewportarray.jpg and /dev/null differ diff --git a/screenshots/vulkanscene.jpg b/screenshots/vulkanscene.jpg deleted file mode 100644 index cee560fe..00000000 Binary files a/screenshots/vulkanscene.jpg and /dev/null differ diff --git a/shaders/glsl/bloom/colorpass.frag b/shaders/glsl/bloom/colorpass.frag deleted file mode 100644 index d9f74f2d..00000000 --- a/shaders/glsl/bloom/colorpass.frag +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D colorMap; - -layout (location = 0) in vec3 inColor; -layout (location = 1) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor.rgb = inColor; -// outFragColor = texture(colorMap, inUV);// * vec4(inColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/bloom/colorpass.frag.spv b/shaders/glsl/bloom/colorpass.frag.spv deleted file mode 100644 index 71873365..00000000 Binary files a/shaders/glsl/bloom/colorpass.frag.spv and /dev/null differ diff --git a/shaders/glsl/bloom/colorpass.vert b/shaders/glsl/bloom/colorpass.vert deleted file mode 100644 index 565f2ddc..00000000 --- a/shaders/glsl/bloom/colorpass.vert +++ /dev/null @@ -1,27 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outColor; -layout (location = 1) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = inUV; - outColor = inColor; - gl_Position = ubo.projection * ubo.view * ubo.model * inPos; -} diff --git a/shaders/glsl/bloom/colorpass.vert.spv b/shaders/glsl/bloom/colorpass.vert.spv deleted file mode 100644 index 86c3ca64..00000000 Binary files a/shaders/glsl/bloom/colorpass.vert.spv and /dev/null differ diff --git a/shaders/glsl/bloom/gaussblur.frag b/shaders/glsl/bloom/gaussblur.frag deleted file mode 100644 index 3758f6c7..00000000 --- a/shaders/glsl/bloom/gaussblur.frag +++ /dev/null @@ -1,44 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (binding = 0) uniform UBO -{ - float blurScale; - float blurStrength; -} ubo; - -layout (constant_id = 0) const int blurdirection = 0; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - float weight[5]; - weight[0] = 0.227027; - weight[1] = 0.1945946; - weight[2] = 0.1216216; - weight[3] = 0.054054; - weight[4] = 0.016216; - - vec2 tex_offset = 1.0 / textureSize(samplerColor, 0) * ubo.blurScale; // gets size of single texel - vec3 result = texture(samplerColor, inUV).rgb * weight[0]; // current fragment's contribution - for(int i = 1; i < 5; ++i) - { - if (blurdirection == 1) - { - // H - result += texture(samplerColor, inUV + vec2(tex_offset.x * i, 0.0)).rgb * weight[i] * ubo.blurStrength; - result += texture(samplerColor, inUV - vec2(tex_offset.x * i, 0.0)).rgb * weight[i] * ubo.blurStrength; - } - else - { - // V - result += texture(samplerColor, inUV + vec2(0.0, tex_offset.y * i)).rgb * weight[i] * ubo.blurStrength; - result += texture(samplerColor, inUV - vec2(0.0, tex_offset.y * i)).rgb * weight[i] * ubo.blurStrength; - } - } - outFragColor = vec4(result, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/bloom/gaussblur.frag.spv b/shaders/glsl/bloom/gaussblur.frag.spv deleted file mode 100644 index 328633b4..00000000 Binary files a/shaders/glsl/bloom/gaussblur.frag.spv and /dev/null differ diff --git a/shaders/glsl/bloom/gaussblur.vert b/shaders/glsl/bloom/gaussblur.vert deleted file mode 100644 index a5d60d0e..00000000 --- a/shaders/glsl/bloom/gaussblur.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/bloom/gaussblur.vert.spv b/shaders/glsl/bloom/gaussblur.vert.spv deleted file mode 100644 index 4040f608..00000000 Binary files a/shaders/glsl/bloom/gaussblur.vert.spv and /dev/null differ diff --git a/shaders/glsl/bloom/phongpass.frag b/shaders/glsl/bloom/phongpass.frag deleted file mode 100644 index e748d460..00000000 --- a/shaders/glsl/bloom/phongpass.frag +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D colorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 ambient = vec3(0.0f); - - // Adjust light calculations for glow color - if ((inColor.r >= 0.9) || (inColor.g >= 0.9) || (inColor.b >= 0.9)) - { - ambient = inColor * 0.25; - } - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * inColor; - vec3 specular = pow(max(dot(R, V), 0.0), 8.0) * vec3(0.75); - outFragColor = vec4(ambient + diffuse + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/bloom/phongpass.frag.spv b/shaders/glsl/bloom/phongpass.frag.spv deleted file mode 100644 index 27e5b53a..00000000 Binary files a/shaders/glsl/bloom/phongpass.frag.spv and /dev/null differ diff --git a/shaders/glsl/bloom/phongpass.vert b/shaders/glsl/bloom/phongpass.vert deleted file mode 100644 index 1c5618b2..00000000 --- a/shaders/glsl/bloom/phongpass.vert +++ /dev/null @@ -1,38 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; -layout (location = 2) out vec3 outColor; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - outUV = inUV; - gl_Position = ubo.projection * ubo.view * ubo.model * inPos; - - vec3 lightPos = vec3(-5.0, -5.0, 0.0); - vec4 pos = ubo.view * ubo.model * inPos; - outNormal = mat3(ubo.view * ubo.model) * inNormal; - outLightVec = lightPos - pos.xyz; - outViewVec = -pos.xyz; -} diff --git a/shaders/glsl/bloom/phongpass.vert.spv b/shaders/glsl/bloom/phongpass.vert.spv deleted file mode 100644 index 7fa727f8..00000000 Binary files a/shaders/glsl/bloom/phongpass.vert.spv and /dev/null differ diff --git a/shaders/glsl/bloom/skybox.frag b/shaders/glsl/bloom/skybox.frag deleted file mode 100644 index 56b8f42c..00000000 --- a/shaders/glsl/bloom/skybox.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (binding = 1) uniform samplerCube samplerCubeMap; - -layout (location = 0) in vec3 inUVW; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerCubeMap, inUVW); -} \ No newline at end of file diff --git a/shaders/glsl/bloom/skybox.frag.spv b/shaders/glsl/bloom/skybox.frag.spv deleted file mode 100644 index 54a894cc..00000000 Binary files a/shaders/glsl/bloom/skybox.frag.spv and /dev/null differ diff --git a/shaders/glsl/bloom/skybox.vert b/shaders/glsl/bloom/skybox.vert deleted file mode 100644 index 3659e407..00000000 --- a/shaders/glsl/bloom/skybox.vert +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outUVW; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - - -void main() -{ - outUVW = inPos; - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/bloom/skybox.vert.spv b/shaders/glsl/bloom/skybox.vert.spv deleted file mode 100644 index c62b7c47..00000000 Binary files a/shaders/glsl/bloom/skybox.vert.spv and /dev/null differ diff --git a/shaders/glsl/bufferdeviceaddress/cube.frag b/shaders/glsl/bufferdeviceaddress/cube.frag deleted file mode 100644 index 0feb8ede..00000000 --- a/shaders/glsl/bufferdeviceaddress/cube.frag +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (c) 2024, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 450 - -layout (set = 0, binding = 0) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerColorMap, inUV) * vec4(inColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/bufferdeviceaddress/cube.frag.spv b/shaders/glsl/bufferdeviceaddress/cube.frag.spv deleted file mode 100644 index 92a0dfa3..00000000 Binary files a/shaders/glsl/bufferdeviceaddress/cube.frag.spv and /dev/null differ diff --git a/shaders/glsl/bufferdeviceaddress/cube.vert b/shaders/glsl/bufferdeviceaddress/cube.vert deleted file mode 100644 index 0bf5c602..00000000 --- a/shaders/glsl/bufferdeviceaddress/cube.vert +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2024, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 450 - -#extension GL_EXT_scalar_block_layout: require -#extension GL_EXT_buffer_reference : require - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -layout (buffer_reference, scalar) readonly buffer MatrixReference { - mat4 matrix; -}; - -layout (push_constant) uniform PushConstants -{ - // Pointer to the buffer with the scene's MVP matrix - MatrixReference sceneDataReference; - // Pointer to the buffer for the data for each model - MatrixReference modelDataReference; -} pushConstants; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec2 outUV; - -void main() -{ - MatrixReference sceneData = pushConstants.sceneDataReference; - MatrixReference modelData = pushConstants.modelDataReference; - - outNormal = inNormal; - outColor = inColor; - outUV = inUV; - gl_Position = sceneData.matrix * modelData.matrix * vec4(inPos.xyz, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/bufferdeviceaddress/cube.vert.spv b/shaders/glsl/bufferdeviceaddress/cube.vert.spv deleted file mode 100644 index 55d16de3..00000000 Binary files a/shaders/glsl/bufferdeviceaddress/cube.vert.spv and /dev/null differ diff --git a/shaders/glsl/computecloth/cloth.comp b/shaders/glsl/computecloth/cloth.comp deleted file mode 100644 index cda4fa20..00000000 --- a/shaders/glsl/computecloth/cloth.comp +++ /dev/null @@ -1,145 +0,0 @@ -#version 450 - -struct Particle { - vec4 pos; - vec4 vel; - vec4 uv; - vec4 normal; -}; - -layout(std430, binding = 0) buffer ParticleIn { - Particle particleIn[ ]; -}; - -layout(std430, binding = 1) buffer ParticleOut { - Particle particleOut[ ]; -}; - -// todo: use shared memory to speed up calculation - -layout (local_size_x = 10, local_size_y = 10) in; - -layout (binding = 2) uniform UBO -{ - float deltaT; - float particleMass; - float springStiffness; - float damping; - float restDistH; - float restDistV; - float restDistD; - float sphereRadius; - vec4 spherePos; - vec4 gravity; - ivec2 particleCount; -} params; - -layout (push_constant) uniform PushConsts { - uint calculateNormals; -} pushConsts; - -vec3 springForce(vec3 p0, vec3 p1, float restDist) -{ - vec3 dist = p0 - p1; - return normalize(dist) * params.springStiffness * (length(dist) - restDist); -} - -void main() -{ - uvec3 id = gl_GlobalInvocationID; - - uint index = id.y * params.particleCount.x + id.x; - if (index > params.particleCount.x * params.particleCount.y) - return; - - // Initial force from gravity - vec3 force = params.gravity.xyz * params.particleMass; - - vec3 pos = particleIn[index].pos.xyz; - vec3 vel = particleIn[index].vel.xyz; - - // Spring forces from neighboring particles - // left - if (id.x > 0) { - force += springForce(particleIn[index-1].pos.xyz, pos, params.restDistH); - } - // right - if (id.x < params.particleCount.x - 1) { - force += springForce(particleIn[index + 1].pos.xyz, pos, params.restDistH); - } - // upper - if (id.y < params.particleCount.y - 1) { - force += springForce(particleIn[index + params.particleCount.x].pos.xyz, pos, params.restDistV); - } - // lower - if (id.y > 0) { - force += springForce(particleIn[index - params.particleCount.x].pos.xyz, pos, params.restDistV); - } - // upper-left - if ((id.x > 0) && (id.y < params.particleCount.y - 1)) { - force += springForce(particleIn[index + params.particleCount.x - 1].pos.xyz, pos, params.restDistD); - } - // lower-left - if ((id.x > 0) && (id.y > 0)) { - force += springForce(particleIn[index - params.particleCount.x - 1].pos.xyz, pos, params.restDistD); - } - // upper-right - if ((id.x < params.particleCount.x - 1) && (id.y < params.particleCount.y - 1)) { - force += springForce(particleIn[index + params.particleCount.x + 1].pos.xyz, pos, params.restDistD); - } - // lower-right - if ((id.x < params.particleCount.x - 1) && (id.y > 0)) { - force += springForce(particleIn[index - params.particleCount.x + 1].pos.xyz, pos, params.restDistD); - } - - force += (-params.damping * vel); - - // Integrate - vec3 f = force * (1.0 / params.particleMass); - particleOut[index].pos = vec4(pos + vel * params.deltaT + 0.5 * f * params.deltaT * params.deltaT, 1.0); - particleOut[index].vel = vec4(vel + f * params.deltaT, 0.0); - - // Sphere collision - vec3 sphereDist = particleOut[index].pos.xyz - params.spherePos.xyz; - if (length(sphereDist) < params.sphereRadius + 0.01) { - // If the particle is inside the sphere, push it to the outer radius - particleOut[index].pos.xyz = params.spherePos.xyz + normalize(sphereDist) * (params.sphereRadius + 0.01); - // Cancel out velocity - particleOut[index].vel = vec4(0.0); - } - - // Normals - if (pushConsts.calculateNormals == 1) { - vec3 normal = vec3(0.0); - vec3 a, b, c; - if (id.y > 0) { - if (id.x > 0) { - a = particleIn[index - 1].pos.xyz - pos; - b = particleIn[index - params.particleCount.x - 1].pos.xyz - pos; - c = particleIn[index - params.particleCount.x].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - if (id.x < params.particleCount.x - 1) { - a = particleIn[index - params.particleCount.x].pos.xyz - pos; - b = particleIn[index - params.particleCount.x + 1].pos.xyz - pos; - c = particleIn[index + 1].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - } - if (id.y < params.particleCount.y - 1) { - if (id.x > 0) { - a = particleIn[index + params.particleCount.x].pos.xyz - pos; - b = particleIn[index + params.particleCount.x - 1].pos.xyz - pos; - c = particleIn[index - 1].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - if (id.x < params.particleCount.x - 1) { - a = particleIn[index + 1].pos.xyz - pos; - b = particleIn[index + params.particleCount.x + 1].pos.xyz - pos; - c = particleIn[index + params.particleCount.x].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - } - particleOut[index].normal = vec4(normalize(normal), 0.0f); - } -} \ No newline at end of file diff --git a/shaders/glsl/computecloth/cloth.comp.spv b/shaders/glsl/computecloth/cloth.comp.spv deleted file mode 100644 index bb505302..00000000 Binary files a/shaders/glsl/computecloth/cloth.comp.spv and /dev/null differ diff --git a/shaders/glsl/computecloth/cloth.frag b/shaders/glsl/computecloth/cloth.frag deleted file mode 100644 index e5f30db5..00000000 --- a/shaders/glsl/computecloth/cloth.frag +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main () -{ - vec3 color = texture(samplerColor, inUV).rgb; - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.15) * vec3(1.0); - vec3 specular = pow(max(dot(R, V), 0.0), 8.0) * vec3(0.2); - outFragColor = vec4(diffuse * color.rgb + specular, 1.0); -} diff --git a/shaders/glsl/computecloth/cloth.frag.spv b/shaders/glsl/computecloth/cloth.frag.spv deleted file mode 100644 index f7102ce0..00000000 Binary files a/shaders/glsl/computecloth/cloth.frag.spv and /dev/null differ diff --git a/shaders/glsl/computecloth/cloth.vert b/shaders/glsl/computecloth/cloth.vert deleted file mode 100644 index 2d640c67..00000000 --- a/shaders/glsl/computecloth/cloth.vert +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inNormal; - -layout (location = 0) out vec2 outUV; -layout (location = 1) out vec3 outNormal; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec4 lightPos; -} ubo; - -void main () -{ - outUV = inUV; - outNormal = inNormal.xyz; - vec4 eyePos = ubo.modelview * vec4(inPos.x, inPos.y, inPos.z, 1.0); - gl_Position = ubo.projection * eyePos; - vec4 pos = vec4(inPos, 1.0); - vec3 lPos = ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/computecloth/cloth.vert.spv b/shaders/glsl/computecloth/cloth.vert.spv deleted file mode 100644 index 480fafa1..00000000 Binary files a/shaders/glsl/computecloth/cloth.vert.spv and /dev/null differ diff --git a/shaders/glsl/computecloth/sphere.frag b/shaders/glsl/computecloth/sphere.frag deleted file mode 100644 index 45be5319..00000000 --- a/shaders/glsl/computecloth/sphere.frag +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inViewVec; -layout (location = 2) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main () -{ - vec3 color = vec3(0.5); - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.15) * vec3(1.0); - vec3 specular = pow(max(dot(R, V), 0.0), 32.0) * vec3(1.0); - outFragColor = vec4(diffuse * color.rgb + specular, 1.0); -} diff --git a/shaders/glsl/computecloth/sphere.frag.spv b/shaders/glsl/computecloth/sphere.frag.spv deleted file mode 100644 index 7ed0c55a..00000000 Binary files a/shaders/glsl/computecloth/sphere.frag.spv and /dev/null differ diff --git a/shaders/glsl/computecloth/sphere.vert b/shaders/glsl/computecloth/sphere.vert deleted file mode 100644 index de6b5a6d..00000000 --- a/shaders/glsl/computecloth/sphere.vert +++ /dev/null @@ -1,31 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 2) in vec3 inNormal; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outViewVec; -layout (location = 2) out vec3 outLightVec; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec4 lightPos; -} ubo; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main () -{ - vec4 eyePos = ubo.modelview * vec4(inPos.x, inPos.y, inPos.z, 1.0); - gl_Position = ubo.projection * eyePos; - vec4 pos = vec4(inPos, 1.0); - vec3 lPos = ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; - outNormal = inNormal; -} \ No newline at end of file diff --git a/shaders/glsl/computecloth/sphere.vert.spv b/shaders/glsl/computecloth/sphere.vert.spv deleted file mode 100644 index 923ecf58..00000000 Binary files a/shaders/glsl/computecloth/sphere.vert.spv and /dev/null differ diff --git a/shaders/glsl/computecullandlod/cull.comp b/shaders/glsl/computecullandlod/cull.comp deleted file mode 100644 index a804c822..00000000 --- a/shaders/glsl/computecullandlod/cull.comp +++ /dev/null @@ -1,110 +0,0 @@ -#version 450 - -layout (constant_id = 0) const int MAX_LOD_LEVEL = 5; - -struct InstanceData -{ - vec3 pos; - float scale; -}; - -// Binding 0: Instance input data for culling -layout (binding = 0, std140) buffer Instances -{ - InstanceData instances[ ]; -}; - -// Same layout as VkDrawIndexedIndirectCommand -struct IndexedIndirectCommand -{ - uint indexCount; - uint instanceCount; - uint firstIndex; - uint vertexOffset; - uint firstInstance; -}; - -// Binding 1: Multi draw output -layout (binding = 1, std430) writeonly buffer IndirectDraws -{ - IndexedIndirectCommand indirectDraws[ ]; -}; - -// Binding 2: Uniform block object with matrices -layout (binding = 2) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec4 cameraPos; - vec4 frustumPlanes[6]; -} ubo; - -// Binding 3: Indirect draw stats -layout (binding = 3) buffer UBOOut -{ - uint drawCount; - uint lodCount[MAX_LOD_LEVEL + 1]; -} uboOut; - -// Binding 4: level-of-detail information -struct LOD -{ - uint firstIndex; - uint indexCount; - float distance; - float _pad0; -}; -layout (binding = 4) readonly buffer LODs -{ - LOD lods[ ]; -}; - -layout (local_size_x = 16) in; - -bool frustumCheck(vec4 pos, float radius) -{ - // Check sphere against frustum planes - for (int i = 0; i < 6; i++) - { - if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0) - { - return false; - } - } - return true; -} - -void main() -{ - uint idx = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x; - - vec4 pos = vec4(instances[idx].pos.xyz, 1.0); - - // Check if object is within current viewing frustum - if (frustumCheck(pos, 1.0)) - { - indirectDraws[idx].instanceCount = 1; - - // Increase number of indirect draw counts - atomicAdd(uboOut.drawCount, 1); - - // Select appropriate LOD level based on distance to camera - uint lodLevel = MAX_LOD_LEVEL; - for (uint i = 0; i < MAX_LOD_LEVEL; i++) - { - if (distance(instances[idx].pos.xyz, ubo.cameraPos.xyz) < lods[i].distance) - { - lodLevel = i; - break; - } - } - indirectDraws[idx].firstIndex = lods[lodLevel].firstIndex; - indirectDraws[idx].indexCount = lods[lodLevel].indexCount; - // Update stats - atomicAdd(uboOut.lodCount[lodLevel], 1); - } - else - { - indirectDraws[idx].instanceCount = 0; - } -} diff --git a/shaders/glsl/computecullandlod/cull.comp.spv b/shaders/glsl/computecullandlod/cull.comp.spv deleted file mode 100644 index b8b6bb0c..00000000 Binary files a/shaders/glsl/computecullandlod/cull.comp.spv and /dev/null differ diff --git a/shaders/glsl/computecullandlod/indirectdraw.frag b/shaders/glsl/computecullandlod/indirectdraw.frag deleted file mode 100644 index 0b7b29dc..00000000 --- a/shaders/glsl/computecullandlod/indirectdraw.frag +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 ambient = vec3(0.25); - vec3 diffuse = vec3(max(dot(N, L), 0.0)); - outFragColor = vec4((ambient + diffuse) * inColor, 1.0); -} diff --git a/shaders/glsl/computecullandlod/indirectdraw.frag.spv b/shaders/glsl/computecullandlod/indirectdraw.frag.spv deleted file mode 100644 index 12c1d44e..00000000 Binary files a/shaders/glsl/computecullandlod/indirectdraw.frag.spv and /dev/null differ diff --git a/shaders/glsl/computecullandlod/indirectdraw.vert b/shaders/glsl/computecullandlod/indirectdraw.vert deleted file mode 100644 index 4335228b..00000000 --- a/shaders/glsl/computecullandlod/indirectdraw.vert +++ /dev/null @@ -1,42 +0,0 @@ -#version 450 - -// Vertex attributes -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -// Instanced attributes -layout (location = 3) in vec3 instancePos; -layout (location = 4) in float instanceScale; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outColor = inColor; - - outNormal = inNormal; - - vec4 pos = vec4((inPos.xyz * instanceScale) + instancePos, 1.0); - - gl_Position = ubo.projection * ubo.modelview * pos; - - vec4 wPos = ubo.modelview * vec4(pos.xyz, 1.0); - vec4 lPos = vec4(0.0, 10.0, 50.0, 1.0); - outLightVec = lPos.xyz - pos.xyz; - outViewVec = -pos.xyz; -} diff --git a/shaders/glsl/computecullandlod/indirectdraw.vert.spv b/shaders/glsl/computecullandlod/indirectdraw.vert.spv deleted file mode 100644 index d94a9ed2..00000000 Binary files a/shaders/glsl/computecullandlod/indirectdraw.vert.spv and /dev/null differ diff --git a/shaders/glsl/computeheadless/headless.comp b/shaders/glsl/computeheadless/headless.comp deleted file mode 100644 index 28be9a6c..00000000 --- a/shaders/glsl/computeheadless/headless.comp +++ /dev/null @@ -1,32 +0,0 @@ -#version 450 - -layout(binding = 0) buffer Pos { - uint values[ ]; -}; - -layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; - -layout (constant_id = 0) const uint BUFFER_ELEMENTS = 32; - -uint fibonacci(uint n) { - if(n <= 1){ - return n; - } - uint curr = 1; - uint prev = 1; - for(uint i = 2; i < n; ++i) { - uint temp = curr; - curr += prev; - prev = temp; - } - return curr; -} - -void main() -{ - uint index = gl_GlobalInvocationID.x; - if (index >= BUFFER_ELEMENTS) - return; - values[index] = fibonacci(values[index]); -} - diff --git a/shaders/glsl/computeheadless/headless.comp.spv b/shaders/glsl/computeheadless/headless.comp.spv deleted file mode 100644 index 54da283a..00000000 Binary files a/shaders/glsl/computeheadless/headless.comp.spv and /dev/null differ diff --git a/shaders/glsl/computenbody/particle.frag b/shaders/glsl/computenbody/particle.frag deleted file mode 100644 index 638c8402..00000000 --- a/shaders/glsl/computenbody/particle.frag +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (binding = 0) uniform sampler2D samplerColorMap; -layout (binding = 1) uniform sampler2D samplerGradientRamp; - -layout (location = 0) in float inGradientPos; - -layout (location = 0) out vec4 outFragColor; - -void main () -{ - vec3 color = texture(samplerGradientRamp, vec2(inGradientPos, 0.0)).rgb; - outFragColor.rgb = texture(samplerColorMap, gl_PointCoord).rgb * color; -} diff --git a/shaders/glsl/computenbody/particle.frag.spv b/shaders/glsl/computenbody/particle.frag.spv deleted file mode 100644 index b9f752f5..00000000 Binary files a/shaders/glsl/computenbody/particle.frag.spv and /dev/null differ diff --git a/shaders/glsl/computenbody/particle.vert b/shaders/glsl/computenbody/particle.vert deleted file mode 100644 index a42963bf..00000000 --- a/shaders/glsl/computenbody/particle.vert +++ /dev/null @@ -1,32 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec4 inVel; - -layout (location = 0) out float outGradientPos; - -layout (binding = 2) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec2 screendim; -} ubo; - -out gl_PerVertex -{ - vec4 gl_Position; - float gl_PointSize; -}; - -void main () -{ - const float spriteSize = 0.005 * inPos.w; // Point size influenced by mass (stored in inPos.w); - - vec4 eyePos = ubo.modelview * vec4(inPos.x, inPos.y, inPos.z, 1.0); - vec4 projectedCorner = ubo.projection * vec4(0.5 * spriteSize, 0.5 * spriteSize, eyePos.z, eyePos.w); - gl_PointSize = clamp(ubo.screendim.x * projectedCorner.x / projectedCorner.w, 1.0, 128.0); - - gl_Position = ubo.projection * eyePos; - - outGradientPos = inVel.w; -} \ No newline at end of file diff --git a/shaders/glsl/computenbody/particle.vert.spv b/shaders/glsl/computenbody/particle.vert.spv deleted file mode 100644 index a89bd16f..00000000 Binary files a/shaders/glsl/computenbody/particle.vert.spv and /dev/null differ diff --git a/shaders/glsl/computenbody/particle_calculate.comp b/shaders/glsl/computenbody/particle_calculate.comp deleted file mode 100644 index 7bdf774e..00000000 --- a/shaders/glsl/computenbody/particle_calculate.comp +++ /dev/null @@ -1,75 +0,0 @@ - -#version 450 - -struct Particle -{ - vec4 pos; - vec4 vel; -}; - -// Binding 0 : Position storage buffer -layout(std140, binding = 0) buffer Pos -{ - Particle particles[ ]; -}; - -layout (local_size_x = 256) in; - -layout (binding = 1) uniform UBO -{ - float deltaT; - int particleCount; - float gravity; - float power; - float soften; -} ubo; - -layout (constant_id = 0) const int SHARED_DATA_SIZE = 512; - -// Share data between computer shader invocations to speed up caluclations -shared vec4 sharedData[SHARED_DATA_SIZE]; - -void main() -{ - // Current SSBO index - uint index = gl_GlobalInvocationID.x; - if (index >= ubo.particleCount) - return; - - vec4 position = particles[index].pos; - vec4 velocity = particles[index].vel; - vec4 acceleration = vec4(0.0); - - for (int i = 0; i < ubo.particleCount; i += SHARED_DATA_SIZE) - { - if (i + gl_LocalInvocationID.x < ubo.particleCount) - { - sharedData[gl_LocalInvocationID.x] = particles[i + gl_LocalInvocationID.x].pos; - } - else - { - sharedData[gl_LocalInvocationID.x] = vec4(0.0); - } - - memoryBarrierShared(); - barrier(); - - for (int j = 0; j < gl_WorkGroupSize.x; j++) - { - vec4 other = sharedData[j]; - vec3 len = other.xyz - position.xyz; - acceleration.xyz += ubo.gravity * len * other.w / pow(dot(len, len) + ubo.soften, ubo.power); - } - - memoryBarrierShared(); - barrier(); - } - - particles[index].vel.xyz += ubo.deltaT * acceleration.xyz; - - // Gradient texture position - particles[index].vel.w += 0.1 * ubo.deltaT; - if (particles[index].vel.w > 1.0) { - particles[index].vel.w -= 1.0; - } -} \ No newline at end of file diff --git a/shaders/glsl/computenbody/particle_calculate.comp.spv b/shaders/glsl/computenbody/particle_calculate.comp.spv deleted file mode 100644 index e52d4137..00000000 Binary files a/shaders/glsl/computenbody/particle_calculate.comp.spv and /dev/null differ diff --git a/shaders/glsl/computenbody/particle_integrate.comp b/shaders/glsl/computenbody/particle_integrate.comp deleted file mode 100644 index 4ac2e07a..00000000 --- a/shaders/glsl/computenbody/particle_integrate.comp +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -struct Particle -{ - vec4 pos; - vec4 vel; -}; - -// Binding 0 : Position storage buffer -layout(std140, binding = 0) buffer Pos -{ - Particle particles[ ]; -}; - -layout (local_size_x = 256) in; - -layout (binding = 1) uniform UBO -{ - float deltaT; - int particleCount; -} ubo; - -void main() -{ - int index = int(gl_GlobalInvocationID); - vec4 position = particles[index].pos; - vec4 velocity = particles[index].vel; - position += ubo.deltaT * velocity; - particles[index].pos = position; -} \ No newline at end of file diff --git a/shaders/glsl/computenbody/particle_integrate.comp.spv b/shaders/glsl/computenbody/particle_integrate.comp.spv deleted file mode 100644 index 477a12a9..00000000 Binary files a/shaders/glsl/computenbody/particle_integrate.comp.spv and /dev/null differ diff --git a/shaders/glsl/computeparticles/particle.comp b/shaders/glsl/computeparticles/particle.comp deleted file mode 100644 index 36a7be18..00000000 --- a/shaders/glsl/computeparticles/particle.comp +++ /dev/null @@ -1,76 +0,0 @@ -#version 450 - -struct Particle -{ - vec2 pos; - vec2 vel; - vec4 gradientPos; -}; - -// Binding 0 : Position storage buffer -layout(std140, binding = 0) buffer Pos -{ - Particle particles[ ]; -}; - -layout (local_size_x = 256) in; - -layout (binding = 1) uniform UBO -{ - float deltaT; - float destX; - float destY; - int particleCount; -} ubo; - -vec2 attraction(vec2 pos, vec2 attractPos) -{ - vec2 delta = attractPos - pos; - const float damp = 0.5; - float dDampedDot = dot(delta, delta) + damp; - float invDist = 1.0f / sqrt(dDampedDot); - float invDistCubed = invDist*invDist*invDist; - return delta * invDistCubed * 0.0035; -} - -vec2 repulsion(vec2 pos, vec2 attractPos) -{ - vec2 delta = attractPos - pos; - float targetDistance = sqrt(dot(delta, delta)); - return delta * (1.0 / (targetDistance * targetDistance * targetDistance)) * -0.000035; -} - -void main() -{ - // Current SSBO index - uint index = gl_GlobalInvocationID.x; - // Don't try to write beyond particle count - if (index >= ubo.particleCount) - return; - - // Read position and velocity - vec2 vVel = particles[index].vel.xy; - vec2 vPos = particles[index].pos.xy; - - vec2 destPos = vec2(ubo.destX, ubo.destY); - - vec2 delta = destPos - vPos; - float targetDistance = sqrt(dot(delta, delta)); - vVel += repulsion(vPos, destPos.xy) * 0.05; - - // Move by velocity - vPos += vVel * ubo.deltaT; - - // collide with boundary - if ((vPos.x < -1.0) || (vPos.x > 1.0) || (vPos.y < -1.0) || (vPos.y > 1.0)) - vVel = (-vVel * 0.1) + attraction(vPos, destPos) * 12; - else - particles[index].pos.xy = vPos; - - // Write back - particles[index].vel.xy = vVel; - particles[index].gradientPos.x += 0.02 * ubo.deltaT; - if (particles[index].gradientPos.x > 1.0) - particles[index].gradientPos.x -= 1.0; -} - diff --git a/shaders/glsl/computeparticles/particle.comp.spv b/shaders/glsl/computeparticles/particle.comp.spv deleted file mode 100644 index 977b98b1..00000000 Binary files a/shaders/glsl/computeparticles/particle.comp.spv and /dev/null differ diff --git a/shaders/glsl/computeparticles/particle.frag b/shaders/glsl/computeparticles/particle.frag deleted file mode 100644 index c7dc1c85..00000000 --- a/shaders/glsl/computeparticles/particle.frag +++ /dev/null @@ -1,15 +0,0 @@ -#version 450 - -layout (binding = 0) uniform sampler2D samplerColorMap; -layout (binding = 1) uniform sampler2D samplerGradientRamp; - -layout (location = 0) in vec4 inColor; -layout (location = 1) in float inGradientPos; - -layout (location = 0) out vec4 outFragColor; - -void main () -{ - vec3 color = texture(samplerGradientRamp, vec2(inGradientPos, 0.0)).rgb; - outFragColor.rgb = texture(samplerColorMap, gl_PointCoord).rgb * color; -} diff --git a/shaders/glsl/computeparticles/particle.frag.spv b/shaders/glsl/computeparticles/particle.frag.spv deleted file mode 100644 index d3d9c746..00000000 Binary files a/shaders/glsl/computeparticles/particle.frag.spv and /dev/null differ diff --git a/shaders/glsl/computeparticles/particle.vert b/shaders/glsl/computeparticles/particle.vert deleted file mode 100644 index 5ff7a2c3..00000000 --- a/shaders/glsl/computeparticles/particle.vert +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout (location = 0) in vec2 inPos; -layout (location = 1) in vec4 inGradientPos; - -layout (location = 0) out vec4 outColor; -layout (location = 1) out float outGradientPos; - -out gl_PerVertex -{ - vec4 gl_Position; - float gl_PointSize; -}; - -void main () -{ - gl_PointSize = 8.0; - outColor = vec4(0.035); - outGradientPos = inGradientPos.x; - gl_Position = vec4(inPos.xy, 1.0, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/computeparticles/particle.vert.spv b/shaders/glsl/computeparticles/particle.vert.spv deleted file mode 100644 index 6a367787..00000000 Binary files a/shaders/glsl/computeparticles/particle.vert.spv and /dev/null differ diff --git a/shaders/glsl/computeraytracing/raytracing.comp b/shaders/glsl/computeraytracing/raytracing.comp deleted file mode 100644 index 256560d4..00000000 --- a/shaders/glsl/computeraytracing/raytracing.comp +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2023 Sascha Willems - -// Shader is looseley based on the ray tracing coding session by Inigo Quilez (www.iquilezles.org) - -#version 450 - -layout (local_size_x = 16, local_size_y = 16) in; -layout (binding = 0, rgba8) uniform writeonly image2D resultImage; - -#define EPSILON 0.0001 -#define MAXLEN 1000.0 -#define SHADOW 0.5 -#define RAYBOUNCES 2 -#define REFLECTIONS true -#define REFLECTIONSTRENGTH 0.4 -#define REFLECTIONFALLOFF 0.5 - -#define SceneObjectTypeSphere 0 -#define SceneObjectTypePlane 1 - -struct Camera -{ - vec3 pos; - vec3 lookat; - float fov; -}; - -layout (binding = 1) uniform UBO -{ - vec3 lightPos; - float aspectRatio; - vec4 fogColor; - Camera camera; - mat4 rotMat; -} ubo; - -struct SceneObject -{ - vec4 objectProperties; - vec3 diffuse; - float specular; - int id; - int objectType; -}; - -layout (std140, binding = 2) buffer SceneObjects -{ - SceneObject sceneObjects[ ]; -}; - -void reflectRay(inout vec3 rayD, in vec3 mormal) -{ - rayD = rayD + 2.0 * -dot(mormal, rayD) * mormal; -} - -// Lighting ========================================================= - -float lightDiffuse(vec3 normal, vec3 lightDir) -{ - return clamp(dot(normal, lightDir), 0.1, 1.0); -} - -float lightSpecular(vec3 normal, vec3 lightDir, float specularFactor) -{ - vec3 viewVec = normalize(ubo.camera.pos); - vec3 halfVec = normalize(lightDir + viewVec); - return pow(clamp(dot(normal, halfVec), 0.0, 1.0), specularFactor); -} - -// Sphere =========================================================== - -float sphereIntersect(in vec3 rayO, in vec3 rayD, in SceneObject sphere) -{ - vec3 oc = rayO - sphere.objectProperties.xyz; - float b = 2.0 * dot(oc, rayD); - float c = dot(oc, oc) - sphere.objectProperties.w * sphere.objectProperties.w; - float h = b*b - 4.0*c; - if (h < 0.0) - { - return -1.0; - } - float t = (-b - sqrt(h)) / 2.0; - - return t; -} - -vec3 sphereNormal(in vec3 pos, in SceneObject sphere) -{ - return (pos - sphere.objectProperties.xyz) / sphere.objectProperties.w; -} - -// Plane =========================================================== - -float planeIntersect(vec3 rayO, vec3 rayD, SceneObject plane) -{ - float d = dot(rayD, plane.objectProperties.xyz); - - if (d == 0.0) - return 0.0; - - float t = -(plane.objectProperties.w + dot(rayO, plane.objectProperties.xyz)) / d; - - if (t < 0.0) - return 0.0; - - return t; -} - - -int intersect(in vec3 rayO, in vec3 rayD, inout float resT) -{ - int id = -1; - float t = -1000.0f; - - for (int i = 0; i < sceneObjects.length(); i++) - { - // Sphere - if (sceneObjects[i].objectType == SceneObjectTypeSphere) { - t = sphereIntersect(rayO, rayD, sceneObjects[i]); - } - // Plane - if (sceneObjects[i].objectType == SceneObjectTypePlane) { - t = planeIntersect(rayO, rayD, sceneObjects[i]); - } - if ((t > EPSILON) && (t < resT)) - { - id = sceneObjects[i].id; - resT = t; - } - } - - return id; -} - -float calcShadow(in vec3 rayO, in vec3 rayD, in int objectId, inout float t) -{ - for (int i = 0; i < sceneObjects.length(); i++) - { - if (sceneObjects[i].id == objectId) - continue; - - float tLoc = MAXLEN; - - // Sphere - if (sceneObjects[i].objectType == SceneObjectTypeSphere) { - tLoc = sphereIntersect(rayO, rayD, sceneObjects[i]); - } - // Plane - if (sceneObjects[i].objectType == SceneObjectTypePlane) { - tLoc = planeIntersect(rayO, rayD, sceneObjects[i]); - } - if ((tLoc > EPSILON) && (tLoc < t)) - { - t = tLoc; - return SHADOW; - } - } - return 1.0; -} - -vec3 fog(in float t, in vec3 color) -{ - return mix(color, ubo.fogColor.rgb, clamp(sqrt(t*t)/20.0, 0.0, 1.0)); -} - -vec3 renderScene(inout vec3 rayO, inout vec3 rayD, inout int id) -{ - vec3 color = vec3(0.0); - float t = MAXLEN; - - // Get intersected object ID - int objectID = intersect(rayO, rayD, t); - - if (objectID == -1) - { - return color; - } - - vec3 pos = rayO + t * rayD; - vec3 lightVec = normalize(ubo.lightPos - pos); - vec3 normal; - - for (int i = 0; i < sceneObjects.length(); i++) - { - if (objectID == sceneObjects[i].id) { - // Sphere - if (sceneObjects[i].objectType == SceneObjectTypeSphere) { - normal = sphereNormal(pos, sceneObjects[i]); - } - // Plane - if (sceneObjects[i].objectType == SceneObjectTypePlane) { - normal = sceneObjects[i].objectProperties.xyz; - } - // Lighting - float diffuse = lightDiffuse(normal, lightVec); - float specular = lightSpecular(normal, lightVec, sceneObjects[i].specular); - color = diffuse * sceneObjects[i].diffuse + specular; - } - } - - if (id == -1) - return color; - - id = objectID; - - // Shadows - t = length(ubo.lightPos - pos); - color *= calcShadow(pos, lightVec, id, t); - - // Fog - color = fog(t, color); - - // Reflect ray for next render pass - reflectRay(rayD, normal); - rayO = pos; - - return color; -} - -void main() -{ - ivec2 dim = imageSize(resultImage); - vec2 uv = vec2(gl_GlobalInvocationID.xy) / dim; - - vec3 rayO = ubo.camera.pos; - vec3 rayD = normalize(vec3((-1.0 + 2.0 * uv) * vec2(ubo.aspectRatio, 1.0), -1.0)); - - // Basic color path - int id = 0; - vec3 finalColor = renderScene(rayO, rayD, id); - - // Reflection - if (REFLECTIONS) - { - float reflectionStrength = REFLECTIONSTRENGTH; - for (int i = 0; i < RAYBOUNCES; i++) - { - vec3 reflectionColor = renderScene(rayO, rayD, id); - finalColor = (1.0 - reflectionStrength) * finalColor + reflectionStrength * mix(reflectionColor, finalColor, 1.0 - reflectionStrength); - reflectionStrength *= REFLECTIONFALLOFF; - } - } - - imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(finalColor, 0.0)); -} \ No newline at end of file diff --git a/shaders/glsl/computeraytracing/raytracing.comp.spv b/shaders/glsl/computeraytracing/raytracing.comp.spv deleted file mode 100644 index 4b706dfe..00000000 Binary files a/shaders/glsl/computeraytracing/raytracing.comp.spv and /dev/null differ diff --git a/shaders/glsl/computeraytracing/texture.frag b/shaders/glsl/computeraytracing/texture.frag deleted file mode 100644 index ecd21f25..00000000 --- a/shaders/glsl/computeraytracing/texture.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (binding = 0) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerColor, vec2(inUV.s, 1.0 - inUV.t)); -} \ No newline at end of file diff --git a/shaders/glsl/computeraytracing/texture.frag.spv b/shaders/glsl/computeraytracing/texture.frag.spv deleted file mode 100644 index 81f30b2f..00000000 Binary files a/shaders/glsl/computeraytracing/texture.frag.spv and /dev/null differ diff --git a/shaders/glsl/computeraytracing/texture.vert b/shaders/glsl/computeraytracing/texture.vert deleted file mode 100644 index 969b8f7f..00000000 --- a/shaders/glsl/computeraytracing/texture.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f + -1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/computeraytracing/texture.vert.spv b/shaders/glsl/computeraytracing/texture.vert.spv deleted file mode 100644 index 3a8d9076..00000000 Binary files a/shaders/glsl/computeraytracing/texture.vert.spv and /dev/null differ diff --git a/shaders/glsl/computeshader/edgedetect.comp b/shaders/glsl/computeshader/edgedetect.comp deleted file mode 100644 index 5c70178d..00000000 --- a/shaders/glsl/computeshader/edgedetect.comp +++ /dev/null @@ -1,44 +0,0 @@ -#version 450 - -layout (local_size_x = 16, local_size_y = 16) in; -layout (binding = 0, rgba8) uniform readonly image2D inputImage; -layout (binding = 1, rgba8) uniform image2D resultImage; - -float conv(in float[9] kernel, in float[9] data, in float denom, in float offset) -{ - float res = 0.0; - for (int i=0; i<9; ++i) - { - res += kernel[i] * data[i]; - } - return clamp(res/denom + offset, 0.0, 1.0); -} - -struct ImageData -{ - float avg[9]; -} imageData; - -void main() -{ - // Fetch neighbouring texels - int n = -1; - for (int i=-1; i<2; ++i) - { - for(int j=-1; j<2; ++j) - { - n++; - vec3 rgb = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x + i, gl_GlobalInvocationID.y + j)).rgb; - imageData.avg[n] = (rgb.r + rgb.g + rgb.b) / 3.0; - } - } - - float[9] kernel; - kernel[0] = -1.0/8.0; kernel[1] = -1.0/8.0; kernel[2] = -1.0/8.0; - kernel[3] = -1.0/8.0; kernel[4] = 1.0; kernel[5] = -1.0/8.0; - kernel[6] = -1.0/8.0; kernel[7] = -1.0/8.0; kernel[8] = -1.0/8.0; - - vec4 res = vec4(vec3(conv(kernel, imageData.avg, 0.1, 0.0)), 1.0); - - imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), res); -} diff --git a/shaders/glsl/computeshader/edgedetect.comp.spv b/shaders/glsl/computeshader/edgedetect.comp.spv deleted file mode 100644 index 66a32b36..00000000 Binary files a/shaders/glsl/computeshader/edgedetect.comp.spv and /dev/null differ diff --git a/shaders/glsl/computeshader/emboss.comp b/shaders/glsl/computeshader/emboss.comp deleted file mode 100644 index 4402d7cd..00000000 --- a/shaders/glsl/computeshader/emboss.comp +++ /dev/null @@ -1,44 +0,0 @@ -#version 450 - -layout (local_size_x = 16, local_size_y = 16) in; -layout (binding = 0, rgba8) uniform readonly image2D inputImage; -layout (binding = 1, rgba8) uniform image2D resultImage; - -float conv(in float[9] kernel, in float[9] data, in float denom, in float offset) -{ - float res = 0.0; - for (int i=0; i<9; ++i) - { - res += kernel[i] * data[i]; - } - return clamp(res/denom + offset, 0.0, 1.0); -} - -struct ImageData -{ - float avg[9]; -} imageData; - -void main() -{ - // Fetch neighbouring texels - int n = -1; - for (int i=-1; i<2; ++i) - { - for(int j=-1; j<2; ++j) - { - n++; - vec3 rgb = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x + i, gl_GlobalInvocationID.y + j)).rgb; - imageData.avg[n] = (rgb.r + rgb.g + rgb.b) / 3.0; - } - } - - float[9] kernel; - kernel[0] = -1.0; kernel[1] = 0.0; kernel[2] = 0.0; - kernel[3] = 0.0; kernel[4] = -1.0; kernel[5] = 0.0; - kernel[6] = 0.0; kernel[7] = 0.0; kernel[8] = 2.0; - - vec4 res = vec4(vec3(conv(kernel, imageData.avg, 1.0, 0.50)), 1.0); - - imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), res); -} \ No newline at end of file diff --git a/shaders/glsl/computeshader/emboss.comp.spv b/shaders/glsl/computeshader/emboss.comp.spv deleted file mode 100644 index 88cc8d79..00000000 Binary files a/shaders/glsl/computeshader/emboss.comp.spv and /dev/null differ diff --git a/shaders/glsl/computeshader/sharpen.comp b/shaders/glsl/computeshader/sharpen.comp deleted file mode 100644 index f94c8e9f..00000000 --- a/shaders/glsl/computeshader/sharpen.comp +++ /dev/null @@ -1,53 +0,0 @@ -#version 450 - -layout (local_size_x = 16, local_size_y = 16) in; -layout (binding = 0, rgba8) uniform readonly image2D inputImage; -layout (binding = 1, rgba8) uniform image2D resultImage; - -float conv(in float[9] kernel, in float[9] data, in float denom, in float offset) -{ - float res = 0.0; - for (int i=0; i<9; ++i) - { - res += kernel[i] * data[i]; - } - return clamp(res/denom + offset, 0.0, 1.0); -} - -struct ImageData -{ - float r[9]; - float g[9]; - float b[9]; -} imageData; - -void main() -{ - - // Fetch neighbouring texels - int n = -1; - for (int i=-1; i<2; ++i) - { - for(int j=-1; j<2; ++j) - { - n++; - vec3 rgb = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x + i, gl_GlobalInvocationID.y + j)).rgb; - imageData.r[n] = rgb.r; - imageData.g[n] = rgb.g; - imageData.b[n] = rgb.b; - } - } - - float[9] kernel; - kernel[0] = -1.0; kernel[1] = -1.0; kernel[2] = -1.0; - kernel[3] = -1.0; kernel[4] = 9.0; kernel[5] = -1.0; - kernel[6] = -1.0; kernel[7] = -1.0; kernel[8] = -1.0; - - vec4 res = vec4( - conv(kernel, imageData.r, 1.0, 0.0), - conv(kernel, imageData.g, 1.0, 0.0), - conv(kernel, imageData.b, 1.0, 0.0), - 1.0); - - imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), res); -} \ No newline at end of file diff --git a/shaders/glsl/computeshader/sharpen.comp.spv b/shaders/glsl/computeshader/sharpen.comp.spv deleted file mode 100644 index f023b768..00000000 Binary files a/shaders/glsl/computeshader/sharpen.comp.spv and /dev/null differ diff --git a/shaders/glsl/computeshader/texture.frag b/shaders/glsl/computeshader/texture.frag deleted file mode 100644 index 108e89b0..00000000 --- a/shaders/glsl/computeshader/texture.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/glsl/computeshader/texture.frag.spv b/shaders/glsl/computeshader/texture.frag.spv deleted file mode 100644 index 401a7434..00000000 Binary files a/shaders/glsl/computeshader/texture.frag.spv and /dev/null differ diff --git a/shaders/glsl/computeshader/texture.vert b/shaders/glsl/computeshader/texture.vert deleted file mode 100644 index 75486072..00000000 --- a/shaders/glsl/computeshader/texture.vert +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; -} ubo; - -layout (location = 0) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = inUV; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/computeshader/texture.vert.spv b/shaders/glsl/computeshader/texture.vert.spv deleted file mode 100644 index f72d6014..00000000 Binary files a/shaders/glsl/computeshader/texture.vert.spv and /dev/null differ diff --git a/shaders/glsl/conditionalrender/model.frag b/shaders/glsl/conditionalrender/model.frag deleted file mode 100644 index aab33e1d..00000000 --- a/shaders/glsl/conditionalrender/model.frag +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 ambient = vec3(0.1); - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); - outFragColor = vec4((ambient + diffuse) * inColor.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/conditionalrender/model.frag.spv b/shaders/glsl/conditionalrender/model.frag.spv deleted file mode 100644 index 33607eb7..00000000 Binary files a/shaders/glsl/conditionalrender/model.frag.spv and /dev/null differ diff --git a/shaders/glsl/conditionalrender/model.vert b/shaders/glsl/conditionalrender/model.vert deleted file mode 100644 index 9be6be0c..00000000 --- a/shaders/glsl/conditionalrender/model.vert +++ /dev/null @@ -1,44 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (set = 0, binding = 0) uniform UBO { - mat4 projection; - mat4 view; - mat4 model; -} ubo; - -layout (set = 1, binding = 0) uniform Node { - mat4 matrix; -} node; - -layout(push_constant) uniform PushBlock { - vec4 baseColorFactor; -} material; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outNormal = inNormal; - outColor = material.baseColorFactor.rgb; - vec4 pos = vec4(inPos, 1.0); - gl_Position = ubo.projection * ubo.view * ubo.model * node.matrix * pos; - - outNormal = mat3(ubo.view * ubo.model * node.matrix) * inNormal; - - vec4 localpos = ubo.view * ubo.model * node.matrix * pos; - vec3 lightPos = vec3(10.0f, -10.0f, 10.0f); - outLightVec = lightPos.xyz - localpos.xyz; - outViewVec = -localpos.xyz; -} diff --git a/shaders/glsl/conditionalrender/model.vert.spv b/shaders/glsl/conditionalrender/model.vert.spv deleted file mode 100644 index 4ab97f4c..00000000 Binary files a/shaders/glsl/conditionalrender/model.vert.spv and /dev/null differ diff --git a/shaders/glsl/conservativeraster/fullscreen.frag b/shaders/glsl/conservativeraster/fullscreen.frag deleted file mode 100644 index b46ee0d3..00000000 --- a/shaders/glsl/conservativeraster/fullscreen.frag +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 - -layout (binding = 0) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/glsl/conservativeraster/fullscreen.frag.spv b/shaders/glsl/conservativeraster/fullscreen.frag.spv deleted file mode 100644 index a4aedf4a..00000000 Binary files a/shaders/glsl/conservativeraster/fullscreen.frag.spv and /dev/null differ diff --git a/shaders/glsl/conservativeraster/fullscreen.vert b/shaders/glsl/conservativeraster/fullscreen.vert deleted file mode 100644 index a5d60d0e..00000000 --- a/shaders/glsl/conservativeraster/fullscreen.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/conservativeraster/fullscreen.vert.spv b/shaders/glsl/conservativeraster/fullscreen.vert.spv deleted file mode 100644 index 4040f608..00000000 Binary files a/shaders/glsl/conservativeraster/fullscreen.vert.spv and /dev/null differ diff --git a/shaders/glsl/conservativeraster/triangle.frag b/shaders/glsl/conservativeraster/triangle.frag deleted file mode 100644 index 8af8ccc0..00000000 --- a/shaders/glsl/conservativeraster/triangle.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor.rgb = inColor; -} \ No newline at end of file diff --git a/shaders/glsl/conservativeraster/triangle.frag.spv b/shaders/glsl/conservativeraster/triangle.frag.spv deleted file mode 100644 index 798349ba..00000000 Binary files a/shaders/glsl/conservativeraster/triangle.frag.spv and /dev/null differ diff --git a/shaders/glsl/conservativeraster/triangle.vert b/shaders/glsl/conservativeraster/triangle.vert deleted file mode 100644 index a8dc0064..00000000 --- a/shaders/glsl/conservativeraster/triangle.vert +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outColor; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outColor = inColor; - gl_Position = ubo.projection * ubo.model * vec4(inPos, 1.0); -} diff --git a/shaders/glsl/conservativeraster/triangle.vert.spv b/shaders/glsl/conservativeraster/triangle.vert.spv deleted file mode 100644 index d664f43c..00000000 Binary files a/shaders/glsl/conservativeraster/triangle.vert.spv and /dev/null differ diff --git a/shaders/glsl/conservativeraster/triangleoverlay.frag b/shaders/glsl/conservativeraster/triangleoverlay.frag deleted file mode 100644 index 1c4fa467..00000000 --- a/shaders/glsl/conservativeraster/triangleoverlay.frag +++ /dev/null @@ -1,8 +0,0 @@ -#version 450 - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor.rgb = vec3(1.0, 1.0, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/conservativeraster/triangleoverlay.frag.spv b/shaders/glsl/conservativeraster/triangleoverlay.frag.spv deleted file mode 100644 index 70e4b065..00000000 Binary files a/shaders/glsl/conservativeraster/triangleoverlay.frag.spv and /dev/null differ diff --git a/shaders/glsl/debugprintf/toon.frag b/shaders/glsl/debugprintf/toon.frag deleted file mode 100644 index b947da36..00000000 --- a/shaders/glsl/debugprintf/toon.frag +++ /dev/null @@ -1,35 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - // Desaturate color - vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65)); - - // High ambient colors because mesh materials are pretty dark - vec3 ambient = color * vec3(1.0); - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * color; - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); - outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0); - - float intensity = dot(N,L); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - outFragColor.rgb = inColor * 3.0 * shade; -} \ No newline at end of file diff --git a/shaders/glsl/debugprintf/toon.frag.spv b/shaders/glsl/debugprintf/toon.frag.spv deleted file mode 100644 index e28490d3..00000000 Binary files a/shaders/glsl/debugprintf/toon.frag.spv and /dev/null differ diff --git a/shaders/glsl/debugprintf/toon.vert b/shaders/glsl/debugprintf/toon.vert deleted file mode 100644 index d383bc20..00000000 --- a/shaders/glsl/debugprintf/toon.vert +++ /dev/null @@ -1,37 +0,0 @@ -#version 450 - -// This extension is required to use printf -#extension GL_EXT_debug_printf : enable - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - - // Output the vertex position using debug printf - debugPrintfEXT("Position = %v4f", pos); - - outNormal = mat3(ubo.model) * inNormal; - vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/debugprintf/toon.vert.spv b/shaders/glsl/debugprintf/toon.vert.spv deleted file mode 100644 index fbbb58c5..00000000 Binary files a/shaders/glsl/debugprintf/toon.vert.spv and /dev/null differ diff --git a/shaders/glsl/debugutils/colorpass.frag b/shaders/glsl/debugutils/colorpass.frag deleted file mode 100644 index 8af8ccc0..00000000 --- a/shaders/glsl/debugutils/colorpass.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor.rgb = inColor; -} \ No newline at end of file diff --git a/shaders/glsl/debugutils/colorpass.frag.spv b/shaders/glsl/debugutils/colorpass.frag.spv deleted file mode 100644 index 798349ba..00000000 Binary files a/shaders/glsl/debugutils/colorpass.frag.spv and /dev/null differ diff --git a/shaders/glsl/debugutils/colorpass.vert b/shaders/glsl/debugutils/colorpass.vert deleted file mode 100644 index 02aca66a..00000000 --- a/shaders/glsl/debugutils/colorpass.vert +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 3) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outColor; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - { - outColor = inColor; - } - gl_Position = ubo.projection * ubo.model * inPos; -} diff --git a/shaders/glsl/debugutils/colorpass.vert.spv b/shaders/glsl/debugutils/colorpass.vert.spv deleted file mode 100644 index 8d613795..00000000 Binary files a/shaders/glsl/debugutils/colorpass.vert.spv and /dev/null differ diff --git a/shaders/glsl/debugutils/postprocess.frag b/shaders/glsl/debugutils/postprocess.frag deleted file mode 100644 index e2a11fd3..00000000 --- a/shaders/glsl/debugutils/postprocess.frag +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - // Single pass gauss blur - - const vec2 texOffset = vec2(0.01, 0.01); - - vec2 tc0 = inUV + vec2(-texOffset.s, -texOffset.t); - vec2 tc1 = inUV + vec2( 0.0, -texOffset.t); - vec2 tc2 = inUV + vec2(+texOffset.s, -texOffset.t); - vec2 tc3 = inUV + vec2(-texOffset.s, 0.0); - vec2 tc4 = inUV + vec2( 0.0, 0.0); - vec2 tc5 = inUV + vec2(+texOffset.s, 0.0); - vec2 tc6 = inUV + vec2(-texOffset.s, +texOffset.t); - vec2 tc7 = inUV + vec2( 0.0, +texOffset.t); - vec2 tc8 = inUV + vec2(+texOffset.s, +texOffset.t); - - vec4 col0 = texture(samplerColor, tc0); - vec4 col1 = texture(samplerColor, tc1); - vec4 col2 = texture(samplerColor, tc2); - vec4 col3 = texture(samplerColor, tc3); - vec4 col4 = texture(samplerColor, tc4); - vec4 col5 = texture(samplerColor, tc5); - vec4 col6 = texture(samplerColor, tc6); - vec4 col7 = texture(samplerColor, tc7); - vec4 col8 = texture(samplerColor, tc8); - - vec4 sum = (1.0 * col0 + 2.0 * col1 + 1.0 * col2 + - 2.0 * col3 + 4.0 * col4 + 2.0 * col5 + - 1.0 * col6 + 2.0 * col7 + 1.0 * col8) / 16.0; - outFragColor = vec4(sum.rgb, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/debugutils/postprocess.frag.spv b/shaders/glsl/debugutils/postprocess.frag.spv deleted file mode 100644 index eb0a125e..00000000 Binary files a/shaders/glsl/debugutils/postprocess.frag.spv and /dev/null differ diff --git a/shaders/glsl/debugutils/postprocess.vert b/shaders/glsl/debugutils/postprocess.vert deleted file mode 100644 index fa4ac1f9..00000000 --- a/shaders/glsl/debugutils/postprocess.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * vec2(2.0f, 2.0f) + vec2(-1.0f, -1.0f), 0.0f, 1.0f); -} \ No newline at end of file diff --git a/shaders/glsl/debugutils/postprocess.vert.spv b/shaders/glsl/debugutils/postprocess.vert.spv deleted file mode 100644 index 57be5820..00000000 Binary files a/shaders/glsl/debugutils/postprocess.vert.spv and /dev/null differ diff --git a/shaders/glsl/debugutils/toon.frag b/shaders/glsl/debugutils/toon.frag deleted file mode 100644 index 622fc86e..00000000 --- a/shaders/glsl/debugutils/toon.frag +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - // Desaturate color - vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65)); - - // High ambient colors because mesh materials are pretty dark - vec3 ambient = color * vec3(1.0); - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * color; - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); - outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0); - - float intensity = dot(N,L); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - outFragColor.rgb = inColor * 3.0 * shade; -} \ No newline at end of file diff --git a/shaders/glsl/debugutils/toon.frag.spv b/shaders/glsl/debugutils/toon.frag.spv deleted file mode 100644 index 62a22eff..00000000 Binary files a/shaders/glsl/debugutils/toon.frag.spv and /dev/null differ diff --git a/shaders/glsl/debugutils/toon.vert b/shaders/glsl/debugutils/toon.vert deleted file mode 100644 index d9139507..00000000 --- a/shaders/glsl/debugutils/toon.vert +++ /dev/null @@ -1,38 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec2 outUV; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - outUV = inUV; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(ubo.model) * inNormal; - vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/debugutils/toon.vert.spv b/shaders/glsl/debugutils/toon.vert.spv deleted file mode 100644 index 82758e68..00000000 Binary files a/shaders/glsl/debugutils/toon.vert.spv and /dev/null differ diff --git a/shaders/glsl/deferred/deferred.frag b/shaders/glsl/deferred/deferred.frag deleted file mode 100644 index a628aa51..00000000 --- a/shaders/glsl/deferred/deferred.frag +++ /dev/null @@ -1,94 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerposition; -layout (binding = 2) uniform sampler2D samplerNormal; -layout (binding = 3) uniform sampler2D samplerAlbedo; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragcolor; - -struct Light { - vec4 position; - vec3 color; - float radius; -}; - -layout (binding = 4) uniform UBO -{ - Light lights[6]; - vec4 viewPos; - int displayDebugTarget; -} ubo; - -void main() -{ - // Get G-Buffer values - vec3 fragPos = texture(samplerposition, inUV).rgb; - vec3 normal = texture(samplerNormal, inUV).rgb; - vec4 albedo = texture(samplerAlbedo, inUV); - - // Debug display - if (ubo.displayDebugTarget > 0) { - switch (ubo.displayDebugTarget) { - case 1: - outFragcolor.rgb = fragPos; - break; - case 2: - outFragcolor.rgb = normal; - break; - case 3: - outFragcolor.rgb = albedo.rgb; - break; - case 4: - outFragcolor.rgb = albedo.aaa; - break; - } - outFragcolor.a = 1.0; - return; - } - - // Render-target composition - - #define lightCount 6 - #define ambient 0.0 - - // Ambient part - vec3 fragcolor = albedo.rgb * ambient; - - for(int i = 0; i < lightCount; ++i) - { - // Vector to light - vec3 L = ubo.lights[i].position.xyz - fragPos; - // Distance from light to fragment position - float dist = length(L); - - // Viewer to fragment - vec3 V = ubo.viewPos.xyz - fragPos; - V = normalize(V); - - //if(dist < ubo.lights[i].radius) - { - // Light to fragment - L = normalize(L); - - // Attenuation - float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0); - - // Diffuse part - vec3 N = normalize(normal); - float NdotL = max(0.0, dot(N, L)); - vec3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten; - - // Specular part - // Specular map values are stored in alpha of albedo mrt - vec3 R = reflect(-L, N); - float NdotR = max(0.0, dot(R, V)); - vec3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 16.0) * atten; - - fragcolor += diff + spec; - } - } - - outFragcolor = vec4(fragcolor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/deferred/deferred.frag.spv b/shaders/glsl/deferred/deferred.frag.spv deleted file mode 100644 index c80c3af1..00000000 Binary files a/shaders/glsl/deferred/deferred.frag.spv and /dev/null differ diff --git a/shaders/glsl/deferred/deferred.vert b/shaders/glsl/deferred/deferred.vert deleted file mode 100644 index 3a42f3c5..00000000 --- a/shaders/glsl/deferred/deferred.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/deferred/deferred.vert.spv b/shaders/glsl/deferred/deferred.vert.spv deleted file mode 100644 index 5683fcb3..00000000 Binary files a/shaders/glsl/deferred/deferred.vert.spv and /dev/null differ diff --git a/shaders/glsl/deferred/mrt.frag b/shaders/glsl/deferred/mrt.frag deleted file mode 100644 index 1aa99da8..00000000 --- a/shaders/glsl/deferred/mrt.frag +++ /dev/null @@ -1,29 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; -layout (binding = 2) uniform sampler2D samplerNormalMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inWorldPos; -layout (location = 4) in vec3 inTangent; - -layout (location = 0) out vec4 outPosition; -layout (location = 1) out vec4 outNormal; -layout (location = 2) out vec4 outAlbedo; - -void main() -{ - outPosition = vec4(inWorldPos, 1.0); - - // Calculate normal in tangent space - vec3 N = normalize(inNormal); - vec3 T = normalize(inTangent); - vec3 B = cross(N, T); - mat3 TBN = mat3(T, B, N); - vec3 tnorm = TBN * normalize(texture(samplerNormalMap, inUV).xyz * 2.0 - vec3(1.0)); - outNormal = vec4(tnorm, 1.0); - - outAlbedo = texture(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/glsl/deferred/mrt.frag.spv b/shaders/glsl/deferred/mrt.frag.spv deleted file mode 100644 index 98c20d13..00000000 Binary files a/shaders/glsl/deferred/mrt.frag.spv and /dev/null differ diff --git a/shaders/glsl/deferred/mrt.vert b/shaders/glsl/deferred/mrt.vert deleted file mode 100644 index 5c564fb4..00000000 --- a/shaders/glsl/deferred/mrt.vert +++ /dev/null @@ -1,41 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inNormal; -layout (location = 4) in vec3 inTangent; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - vec4 instancePos[3]; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; -layout (location = 2) out vec3 outColor; -layout (location = 3) out vec3 outWorldPos; -layout (location = 4) out vec3 outTangent; - -void main() -{ - vec4 tmpPos = inPos + ubo.instancePos[gl_InstanceIndex]; - - gl_Position = ubo.projection * ubo.view * ubo.model * tmpPos; - - outUV = inUV; - - // Vertex position in world space - outWorldPos = vec3(ubo.model * tmpPos); - - // Normal in world space - mat3 mNormal = transpose(inverse(mat3(ubo.model))); - outNormal = mNormal * normalize(inNormal); - outTangent = mNormal * normalize(inTangent); - - // Currently just vertex color - outColor = inColor; -} diff --git a/shaders/glsl/deferred/mrt.vert.spv b/shaders/glsl/deferred/mrt.vert.spv deleted file mode 100644 index d3946c0a..00000000 Binary files a/shaders/glsl/deferred/mrt.vert.spv and /dev/null differ diff --git a/shaders/glsl/deferredmultisampling/deferred.frag b/shaders/glsl/deferredmultisampling/deferred.frag deleted file mode 100644 index 3c882889..00000000 --- a/shaders/glsl/deferredmultisampling/deferred.frag +++ /dev/null @@ -1,120 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2DMS samplerPosition; -layout (binding = 2) uniform sampler2DMS samplerNormal; -layout (binding = 3) uniform sampler2DMS samplerAlbedo; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragcolor; - -struct Light { - vec4 position; - vec3 color; - float radius; -}; - -layout (binding = 4) uniform UBO -{ - Light lights[6]; - vec4 viewPos; - int debugDisplayTarget; -} ubo; - -layout (constant_id = 0) const int NUM_SAMPLES = 8; - -#define NUM_LIGHTS 6 - -// Manual resolve for MSAA samples -vec4 resolve(sampler2DMS tex, ivec2 uv) -{ - vec4 result = vec4(0.0); - for (int i = 0; i < NUM_SAMPLES; i++) - { - vec4 val = texelFetch(tex, uv, i); - result += val; - } - // Average resolved samples - return result / float(NUM_SAMPLES); -} - -vec3 calculateLighting(vec3 pos, vec3 normal, vec4 albedo) -{ - vec3 result = vec3(0.0); - - for(int i = 0; i < NUM_LIGHTS; ++i) - { - // Vector to light - vec3 L = ubo.lights[i].position.xyz - pos; - // Distance from light to fragment position - float dist = length(L); - - // Viewer to fragment - vec3 V = ubo.viewPos.xyz - pos; - V = normalize(V); - - // Light to fragment - L = normalize(L); - - // Attenuation - float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0); - - // Diffuse part - vec3 N = normalize(normal); - float NdotL = max(0.0, dot(N, L)); - vec3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten; - - // Specular part - vec3 R = reflect(-L, N); - float NdotR = max(0.0, dot(R, V)); - vec3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 8.0) * atten; - - result += diff + spec; - } - return result; -} - -void main() -{ - ivec2 attDim = textureSize(samplerPosition); - ivec2 UV = ivec2(inUV * attDim); - - // Debug display - if (ubo.debugDisplayTarget > 0) { - switch (ubo.debugDisplayTarget) { - case 1: - outFragcolor.rgb = texelFetch(samplerPosition, UV, 0).rgb; - break; - case 2: - outFragcolor.rgb = texelFetch(samplerNormal, UV, 0).rgb; - break; - case 3: - outFragcolor.rgb = texelFetch(samplerAlbedo, UV, 0).rgb; - break; - case 4: - outFragcolor.rgb = texelFetch(samplerAlbedo, UV, 0).aaa; - break; - } - outFragcolor.a = 1.0; - return; - } - - #define ambient 0.15 - - // Ambient part - vec4 alb = resolve(samplerAlbedo, UV); - vec3 fragColor = vec3(0.0); - - // Calualte lighting for every MSAA sample - for (int i = 0; i < NUM_SAMPLES; i++) - { - vec3 pos = texelFetch(samplerPosition, UV, i).rgb; - vec3 normal = texelFetch(samplerNormal, UV, i).rgb; - vec4 albedo = texelFetch(samplerAlbedo, UV, i); - fragColor += calculateLighting(pos, normal, albedo); - } - - fragColor = (alb.rgb * ambient) + fragColor / float(NUM_SAMPLES); - - outFragcolor = vec4(fragColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/deferredmultisampling/deferred.frag.spv b/shaders/glsl/deferredmultisampling/deferred.frag.spv deleted file mode 100644 index 2388689c..00000000 Binary files a/shaders/glsl/deferredmultisampling/deferred.frag.spv and /dev/null differ diff --git a/shaders/glsl/deferredmultisampling/deferred.vert b/shaders/glsl/deferredmultisampling/deferred.vert deleted file mode 100644 index 3a42f3c5..00000000 --- a/shaders/glsl/deferredmultisampling/deferred.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/deferredmultisampling/deferred.vert.spv b/shaders/glsl/deferredmultisampling/deferred.vert.spv deleted file mode 100644 index 5683fcb3..00000000 Binary files a/shaders/glsl/deferredmultisampling/deferred.vert.spv and /dev/null differ diff --git a/shaders/glsl/deferredmultisampling/mrt.frag b/shaders/glsl/deferredmultisampling/mrt.frag deleted file mode 100644 index 1aa99da8..00000000 --- a/shaders/glsl/deferredmultisampling/mrt.frag +++ /dev/null @@ -1,29 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; -layout (binding = 2) uniform sampler2D samplerNormalMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inWorldPos; -layout (location = 4) in vec3 inTangent; - -layout (location = 0) out vec4 outPosition; -layout (location = 1) out vec4 outNormal; -layout (location = 2) out vec4 outAlbedo; - -void main() -{ - outPosition = vec4(inWorldPos, 1.0); - - // Calculate normal in tangent space - vec3 N = normalize(inNormal); - vec3 T = normalize(inTangent); - vec3 B = cross(N, T); - mat3 TBN = mat3(T, B, N); - vec3 tnorm = TBN * normalize(texture(samplerNormalMap, inUV).xyz * 2.0 - vec3(1.0)); - outNormal = vec4(tnorm, 1.0); - - outAlbedo = texture(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/glsl/deferredmultisampling/mrt.frag.spv b/shaders/glsl/deferredmultisampling/mrt.frag.spv deleted file mode 100644 index 98c20d13..00000000 Binary files a/shaders/glsl/deferredmultisampling/mrt.frag.spv and /dev/null differ diff --git a/shaders/glsl/deferredmultisampling/mrt.vert b/shaders/glsl/deferredmultisampling/mrt.vert deleted file mode 100644 index 4e8bda2b..00000000 --- a/shaders/glsl/deferredmultisampling/mrt.vert +++ /dev/null @@ -1,46 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inNormal; -layout (location = 4) in vec3 inTangent; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - vec4 instancePos[3]; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; -layout (location = 2) out vec3 outColor; -layout (location = 3) out vec3 outWorldPos; -layout (location = 4) out vec3 outTangent; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - vec4 tmpPos = vec4(inPos.xyz, 1.0) + ubo.instancePos[gl_InstanceIndex]; - - gl_Position = ubo.projection * ubo.view * ubo.model * tmpPos; - - outUV = inUV; - - // Vertex position in world space - outWorldPos = vec3(ubo.model * tmpPos); - - // Normal in world space - mat3 mNormal = transpose(inverse(mat3(ubo.model))); - outNormal = mNormal * normalize(inNormal); - outTangent = mNormal * normalize(inTangent); - - // Currently just vertex color - outColor = inColor; -} diff --git a/shaders/glsl/deferredmultisampling/mrt.vert.spv b/shaders/glsl/deferredmultisampling/mrt.vert.spv deleted file mode 100644 index 8edad7b7..00000000 Binary files a/shaders/glsl/deferredmultisampling/mrt.vert.spv and /dev/null differ diff --git a/shaders/glsl/deferredshadows/deferred.frag b/shaders/glsl/deferredshadows/deferred.frag deleted file mode 100644 index c5848f96..00000000 --- a/shaders/glsl/deferredshadows/deferred.frag +++ /dev/null @@ -1,168 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerposition; -layout (binding = 2) uniform sampler2D samplerNormal; -layout (binding = 3) uniform sampler2D samplerAlbedo; -layout (binding = 5) uniform sampler2DArray samplerShadowMap; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -#define LIGHT_COUNT 3 -#define SHADOW_FACTOR 0.25 -#define AMBIENT_LIGHT 0.1 -#define USE_PCF - -struct Light -{ - vec4 position; - vec4 target; - vec4 color; - mat4 viewMatrix; -}; - -layout (binding = 4) uniform UBO -{ - vec4 viewPos; - Light lights[LIGHT_COUNT]; - int useShadows; - int debugDisplayTarget; -} ubo; - -float textureProj(vec4 P, float layer, vec2 offset) -{ - float shadow = 1.0; - vec4 shadowCoord = P / P.w; - shadowCoord.st = shadowCoord.st * 0.5 + 0.5; - - if (shadowCoord.z > -1.0 && shadowCoord.z < 1.0) - { - float dist = texture(samplerShadowMap, vec3(shadowCoord.st + offset, layer)).r; - if (shadowCoord.w > 0.0 && dist < shadowCoord.z) - { - shadow = SHADOW_FACTOR; - } - } - return shadow; -} - -float filterPCF(vec4 sc, float layer) -{ - ivec2 texDim = textureSize(samplerShadowMap, 0).xy; - float scale = 1.5; - float dx = scale * 1.0 / float(texDim.x); - float dy = scale * 1.0 / float(texDim.y); - - float shadowFactor = 0.0; - int count = 0; - int range = 1; - - for (int x = -range; x <= range; x++) - { - for (int y = -range; y <= range; y++) - { - shadowFactor += textureProj(sc, layer, vec2(dx*x, dy*y)); - count++; - } - - } - return shadowFactor / count; -} - -vec3 shadow(vec3 fragcolor, vec3 fragpos) { - for(int i = 0; i < LIGHT_COUNT; ++i) - { - vec4 shadowClip = ubo.lights[i].viewMatrix * vec4(fragpos, 1.0); - - float shadowFactor; - #ifdef USE_PCF - shadowFactor= filterPCF(shadowClip, i); - #else - shadowFactor = textureProj(shadowClip, i, vec2(0.0)); - #endif - - fragcolor *= shadowFactor; - } - return fragcolor; -} - -void main() -{ - // Get G-Buffer values - vec3 fragPos = texture(samplerposition, inUV).rgb; - vec3 normal = texture(samplerNormal, inUV).rgb; - vec4 albedo = texture(samplerAlbedo, inUV); - - // Debug display - if (ubo.debugDisplayTarget > 0) { - switch (ubo.debugDisplayTarget) { - case 1: - outFragColor.rgb = shadow(vec3(1.0), fragPos).rgb; - break; - case 2: - outFragColor.rgb = fragPos; - break; - case 3: - outFragColor.rgb = normal; - break; - case 4: - outFragColor.rgb = albedo.rgb; - break; - case 5: - outFragColor.rgb = albedo.aaa; - break; - } - outFragColor.a = 1.0; - return; - } - - // Ambient part - vec3 fragcolor = albedo.rgb * AMBIENT_LIGHT; - - vec3 N = normalize(normal); - - for(int i = 0; i < LIGHT_COUNT; ++i) - { - // Vector to light - vec3 L = ubo.lights[i].position.xyz - fragPos; - // Distance from light to fragment position - float dist = length(L); - L = normalize(L); - - // Viewer to fragment - vec3 V = ubo.viewPos.xyz - fragPos; - V = normalize(V); - - float lightCosInnerAngle = cos(radians(15.0)); - float lightCosOuterAngle = cos(radians(25.0)); - float lightRange = 100.0; - - // Direction vector from source to target - vec3 dir = normalize(ubo.lights[i].position.xyz - ubo.lights[i].target.xyz); - - // Dual cone spot light with smooth transition between inner and outer angle - float cosDir = dot(L, dir); - float spotEffect = smoothstep(lightCosOuterAngle, lightCosInnerAngle, cosDir); - float heightAttenuation = smoothstep(lightRange, 0.0f, dist); - - // Diffuse lighting - float NdotL = max(0.0, dot(N, L)); - vec3 diff = vec3(NdotL); - - // Specular lighting - vec3 R = reflect(-L, N); - float NdotR = max(0.0, dot(R, V)); - vec3 spec = vec3(pow(NdotR, 16.0) * albedo.a * 2.5); - - fragcolor += vec3((diff + spec) * spotEffect * heightAttenuation) * ubo.lights[i].color.rgb * albedo.rgb; - } - - // Shadow calculations in a separate pass - if (ubo.useShadows > 0) - { - fragcolor = shadow(fragcolor, fragPos); - } - - outFragColor = vec4(fragcolor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/deferredshadows/deferred.frag.spv b/shaders/glsl/deferredshadows/deferred.frag.spv deleted file mode 100644 index 5c431ab8..00000000 Binary files a/shaders/glsl/deferredshadows/deferred.frag.spv and /dev/null differ diff --git a/shaders/glsl/deferredshadows/deferred.vert b/shaders/glsl/deferredshadows/deferred.vert deleted file mode 100644 index 047d67a4..00000000 --- a/shaders/glsl/deferredshadows/deferred.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} \ No newline at end of file diff --git a/shaders/glsl/deferredshadows/deferred.vert.spv b/shaders/glsl/deferredshadows/deferred.vert.spv deleted file mode 100644 index 5683fcb3..00000000 Binary files a/shaders/glsl/deferredshadows/deferred.vert.spv and /dev/null differ diff --git a/shaders/glsl/deferredshadows/geom.spv b/shaders/glsl/deferredshadows/geom.spv deleted file mode 100644 index 0f7a0149..00000000 Binary files a/shaders/glsl/deferredshadows/geom.spv and /dev/null differ diff --git a/shaders/glsl/deferredshadows/mrt.frag b/shaders/glsl/deferredshadows/mrt.frag deleted file mode 100644 index 1aa99da8..00000000 --- a/shaders/glsl/deferredshadows/mrt.frag +++ /dev/null @@ -1,29 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; -layout (binding = 2) uniform sampler2D samplerNormalMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inWorldPos; -layout (location = 4) in vec3 inTangent; - -layout (location = 0) out vec4 outPosition; -layout (location = 1) out vec4 outNormal; -layout (location = 2) out vec4 outAlbedo; - -void main() -{ - outPosition = vec4(inWorldPos, 1.0); - - // Calculate normal in tangent space - vec3 N = normalize(inNormal); - vec3 T = normalize(inTangent); - vec3 B = cross(N, T); - mat3 TBN = mat3(T, B, N); - vec3 tnorm = TBN * normalize(texture(samplerNormalMap, inUV).xyz * 2.0 - vec3(1.0)); - outNormal = vec4(tnorm, 1.0); - - outAlbedo = texture(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/glsl/deferredshadows/mrt.frag.spv b/shaders/glsl/deferredshadows/mrt.frag.spv deleted file mode 100644 index 98c20d13..00000000 Binary files a/shaders/glsl/deferredshadows/mrt.frag.spv and /dev/null differ diff --git a/shaders/glsl/deferredshadows/mrt.vert b/shaders/glsl/deferredshadows/mrt.vert deleted file mode 100644 index 04ef643d..00000000 --- a/shaders/glsl/deferredshadows/mrt.vert +++ /dev/null @@ -1,41 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inNormal; -layout (location = 4) in vec4 inTangent; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - vec4 instancePos[3]; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; -layout (location = 2) out vec3 outColor; -layout (location = 3) out vec3 outWorldPos; -layout (location = 4) out vec3 outTangent; - -void main() -{ - vec4 tmpPos = vec4(inPos.xyz, 1.0) + ubo.instancePos[gl_InstanceIndex]; - - gl_Position = ubo.projection * ubo.view * ubo.model * tmpPos; - - outUV = inUV; - - // Vertex position in world space - outWorldPos = vec3(ubo.model * tmpPos); - - // Normal in world space - mat3 mNormal = transpose(inverse(mat3(ubo.model))); - outNormal = mNormal * normalize(inNormal); - outTangent = mNormal * normalize(inTangent.xyz); - - // Currently just vertex color - outColor = inColor; -} diff --git a/shaders/glsl/deferredshadows/mrt.vert.spv b/shaders/glsl/deferredshadows/mrt.vert.spv deleted file mode 100644 index 11b7f8f8..00000000 Binary files a/shaders/glsl/deferredshadows/mrt.vert.spv and /dev/null differ diff --git a/shaders/glsl/deferredshadows/shadow.geom b/shaders/glsl/deferredshadows/shadow.geom deleted file mode 100644 index 2ca45c97..00000000 --- a/shaders/glsl/deferredshadows/shadow.geom +++ /dev/null @@ -1,27 +0,0 @@ -#version 450 - -#define LIGHT_COUNT 3 - -layout (triangles, invocations = LIGHT_COUNT) in; -layout (triangle_strip, max_vertices = 3) out; - -layout (binding = 0) uniform UBO -{ - mat4 mvp[LIGHT_COUNT]; - vec4 instancePos[3]; -} ubo; - -layout (location = 0) in int inInstanceIndex[]; - -void main() -{ - vec4 instancedPos = ubo.instancePos[inInstanceIndex[0]]; - for (int i = 0; i < gl_in.length(); i++) - { - gl_Layer = gl_InvocationID; - vec4 tmpPos = gl_in[i].gl_Position + instancedPos; - gl_Position = ubo.mvp[gl_InvocationID] * tmpPos; - EmitVertex(); - } - EndPrimitive(); -} diff --git a/shaders/glsl/deferredshadows/shadow.geom.spv b/shaders/glsl/deferredshadows/shadow.geom.spv deleted file mode 100644 index 2af584d2..00000000 Binary files a/shaders/glsl/deferredshadows/shadow.geom.spv and /dev/null differ diff --git a/shaders/glsl/deferredshadows/shadow.vert b/shaders/glsl/deferredshadows/shadow.vert deleted file mode 100644 index 7b432d5b..00000000 --- a/shaders/glsl/deferredshadows/shadow.vert +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; - -layout (location = 0) out int outInstanceIndex; - -void main() -{ - outInstanceIndex = gl_InstanceIndex; - gl_Position = inPos; -} \ No newline at end of file diff --git a/shaders/glsl/deferredshadows/shadow.vert.spv b/shaders/glsl/deferredshadows/shadow.vert.spv deleted file mode 100644 index 903d6cd5..00000000 Binary files a/shaders/glsl/deferredshadows/shadow.vert.spv and /dev/null differ diff --git a/shaders/glsl/descriptorbuffer/cube.frag b/shaders/glsl/descriptorbuffer/cube.frag deleted file mode 100644 index cd331d4a..00000000 --- a/shaders/glsl/descriptorbuffer/cube.frag +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (set = 2, binding = 0) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerColorMap, inUV) * vec4(inColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/descriptorbuffer/cube.frag.spv b/shaders/glsl/descriptorbuffer/cube.frag.spv deleted file mode 100644 index cff0bd93..00000000 Binary files a/shaders/glsl/descriptorbuffer/cube.frag.spv and /dev/null differ diff --git a/shaders/glsl/descriptorbuffer/cube.vert b/shaders/glsl/descriptorbuffer/cube.vert deleted file mode 100644 index 28c2b156..00000000 --- a/shaders/glsl/descriptorbuffer/cube.vert +++ /dev/null @@ -1,31 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -layout (set = 0, binding = 0) uniform UBOCamera { - mat4 projection; - mat4 view; -} camera; - -layout (set = 1, binding = 0) uniform UBOModel { - mat4 matrix; -} model; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec2 outUV; - -out gl_PerVertex { - vec4 gl_Position; -}; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - outUV = inUV; - gl_Position = camera.projection * camera.view * model.matrix * vec4(inPos.xyz, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/descriptorbuffer/cube.vert.spv b/shaders/glsl/descriptorbuffer/cube.vert.spv deleted file mode 100644 index a94bb0f2..00000000 Binary files a/shaders/glsl/descriptorbuffer/cube.vert.spv and /dev/null differ diff --git a/shaders/glsl/descriptorindexing/descriptorindexing.frag b/shaders/glsl/descriptorindexing/descriptorindexing.frag deleted file mode 100644 index ce97215a..00000000 --- a/shaders/glsl/descriptorindexing/descriptorindexing.frag +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2021 Sascha Willems - -#version 450 - -#extension GL_EXT_nonuniform_qualifier : require - -layout (set = 0, binding = 1) uniform sampler2D textures[]; - -layout (location = 0) in vec2 inUV; -layout (location = 1) flat in int inTexIndex; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(textures[nonuniformEXT(inTexIndex)], inUV); -} \ No newline at end of file diff --git a/shaders/glsl/descriptorindexing/descriptorindexing.frag.spv b/shaders/glsl/descriptorindexing/descriptorindexing.frag.spv deleted file mode 100644 index 1e2499ad..00000000 Binary files a/shaders/glsl/descriptorindexing/descriptorindexing.frag.spv and /dev/null differ diff --git a/shaders/glsl/descriptorindexing/descriptorindexing.vert b/shaders/glsl/descriptorindexing/descriptorindexing.vert deleted file mode 100644 index a0428445..00000000 --- a/shaders/glsl/descriptorindexing/descriptorindexing.vert +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2021 Sascha Willems - -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in int inTextureIndex; - -layout (binding = 0) uniform Matrices -{ - mat4 projection; - mat4 view; - mat4 model; -} matrices; - -layout (location = 0) out vec2 outUV; -layout (location = 1) flat out int outTexIndex; - -void main() -{ - outUV = inUV; - outTexIndex = inTextureIndex; - vec4 pos = vec4(inPos, 1.0f); - gl_Position = matrices.projection * matrices.view * matrices.model * pos; -} diff --git a/shaders/glsl/descriptorindexing/descriptorindexing.vert.spv b/shaders/glsl/descriptorindexing/descriptorindexing.vert.spv deleted file mode 100644 index bec53942..00000000 Binary files a/shaders/glsl/descriptorindexing/descriptorindexing.vert.spv and /dev/null differ diff --git a/shaders/glsl/descriptorsets/cube.frag b/shaders/glsl/descriptorsets/cube.frag deleted file mode 100644 index 56fe3518..00000000 --- a/shaders/glsl/descriptorsets/cube.frag +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (set = 0, binding = 1) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerColorMap, inUV) * vec4(inColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/descriptorsets/cube.frag.spv b/shaders/glsl/descriptorsets/cube.frag.spv deleted file mode 100644 index edf35092..00000000 Binary files a/shaders/glsl/descriptorsets/cube.frag.spv and /dev/null differ diff --git a/shaders/glsl/descriptorsets/cube.vert b/shaders/glsl/descriptorsets/cube.vert deleted file mode 100644 index 1d91505e..00000000 --- a/shaders/glsl/descriptorsets/cube.vert +++ /dev/null @@ -1,28 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -layout (set = 0, binding = 0) uniform UBOMatrices { - mat4 projection; - mat4 view; - mat4 model; -} uboMatrices; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec2 outUV; - -out gl_PerVertex { - vec4 gl_Position; -}; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - outUV = inUV; - gl_Position = uboMatrices.projection * uboMatrices.view * uboMatrices.model * vec4(inPos.xyz, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/descriptorsets/cube.vert.spv b/shaders/glsl/descriptorsets/cube.vert.spv deleted file mode 100644 index 86306db8..00000000 Binary files a/shaders/glsl/descriptorsets/cube.vert.spv and /dev/null differ diff --git a/shaders/glsl/displacement/base.frag b/shaders/glsl/displacement/base.frag deleted file mode 100644 index 1d3cb1ba..00000000 --- a/shaders/glsl/displacement/base.frag +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D colorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inEyePos; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(vec3(1.0)); - - outFragColor.rgb = texture(colorMap, inUV).rgb; - - vec3 Eye = normalize(-inEyePos); - vec3 Reflected = normalize(reflect(-inLightVec, inNormal)); - - vec4 IAmbient = vec4(0.0, 0.0, 0.0, 1.0); - vec4 IDiffuse = vec4(1.0) * max(dot(inNormal, inLightVec), 0.0); - - outFragColor = vec4((IAmbient + IDiffuse) * vec4(texture(colorMap, inUV).rgb, 1.0)); -} \ No newline at end of file diff --git a/shaders/glsl/displacement/base.frag.spv b/shaders/glsl/displacement/base.frag.spv deleted file mode 100644 index c6e57c8c..00000000 Binary files a/shaders/glsl/displacement/base.frag.spv and /dev/null differ diff --git a/shaders/glsl/displacement/base.vert b/shaders/glsl/displacement/base.vert deleted file mode 100644 index 61ef8201..00000000 --- a/shaders/glsl/displacement/base.vert +++ /dev/null @@ -1,15 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; - -void main(void) -{ - gl_Position = vec4(inPos.xyz, 1.0); - outUV = inUV; - outNormal = inNormal; -} \ No newline at end of file diff --git a/shaders/glsl/displacement/base.vert.spv b/shaders/glsl/displacement/base.vert.spv deleted file mode 100644 index d1b4a7e9..00000000 Binary files a/shaders/glsl/displacement/base.vert.spv and /dev/null differ diff --git a/shaders/glsl/displacement/displacement.tesc b/shaders/glsl/displacement/displacement.tesc deleted file mode 100644 index abfc21e0..00000000 --- a/shaders/glsl/displacement/displacement.tesc +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec4 lightPos; - float tessAlpha; - float tessStrength; - float tessLevel; -} ubo; - -layout (vertices = 3) out; - -layout (location = 0) in vec3 inNormal[]; -layout (location = 1) in vec2 inUV[]; - -layout (location = 0) out vec3 outNormal[3]; -layout (location = 1) out vec2 outUV[3]; - -void main() -{ - if (gl_InvocationID == 0) - { - gl_TessLevelInner[0] = ubo.tessLevel; - gl_TessLevelOuter[0] = ubo.tessLevel; - gl_TessLevelOuter[1] = ubo.tessLevel; - gl_TessLevelOuter[2] = ubo.tessLevel; - } - - gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; - outNormal[gl_InvocationID] = inNormal[gl_InvocationID]; - outUV[gl_InvocationID] = inUV[gl_InvocationID]; -} diff --git a/shaders/glsl/displacement/displacement.tesc.spv b/shaders/glsl/displacement/displacement.tesc.spv deleted file mode 100644 index 2a7c0f55..00000000 Binary files a/shaders/glsl/displacement/displacement.tesc.spv and /dev/null differ diff --git a/shaders/glsl/displacement/displacement.tese b/shaders/glsl/displacement/displacement.tese deleted file mode 100644 index e9e750ac..00000000 --- a/shaders/glsl/displacement/displacement.tese +++ /dev/null @@ -1,37 +0,0 @@ -#version 450 - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec4 lightPos; - float tessAlpha; - float tessStrength; - float tessLevel; -} ubo; - -layout (binding = 1) uniform sampler2D displacementMap; - -layout(triangles, equal_spacing, cw) in; - -layout (location = 0) in vec3 inNormal[]; -layout (location = 1) in vec2 inUV[]; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; -layout (location = 2) out vec3 outEyesPos; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) + (gl_TessCoord.y * gl_in[1].gl_Position) + (gl_TessCoord.z * gl_in[2].gl_Position); - outUV = gl_TessCoord.x * inUV[0] + gl_TessCoord.y * inUV[1] + gl_TessCoord.z * inUV[2]; - outNormal = gl_TessCoord.x * inNormal[0] + gl_TessCoord.y * inNormal[1] + gl_TessCoord.z * inNormal[2]; - - gl_Position.xyz += normalize(outNormal) * (max(textureLod(displacementMap, outUV.st, 0.0).a, 0.0) * ubo.tessStrength); - - outEyesPos = (gl_Position).xyz; - outLightVec = normalize(ubo.lightPos.xyz - outEyesPos); - - gl_Position = ubo.projection * ubo.modelview * gl_Position; -} \ No newline at end of file diff --git a/shaders/glsl/displacement/displacement.tese.spv b/shaders/glsl/displacement/displacement.tese.spv deleted file mode 100644 index 859a936d..00000000 Binary files a/shaders/glsl/displacement/displacement.tese.spv and /dev/null differ diff --git a/shaders/glsl/distancefieldfonts/bitmap.frag b/shaders/glsl/distancefieldfonts/bitmap.frag deleted file mode 100644 index 084daf2a..00000000 --- a/shaders/glsl/distancefieldfonts/bitmap.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = vec4(texture(samplerColor, inUV).a); -} \ No newline at end of file diff --git a/shaders/glsl/distancefieldfonts/bitmap.frag.spv b/shaders/glsl/distancefieldfonts/bitmap.frag.spv deleted file mode 100644 index 53a6df85..00000000 Binary files a/shaders/glsl/distancefieldfonts/bitmap.frag.spv and /dev/null differ diff --git a/shaders/glsl/distancefieldfonts/bitmap.vert b/shaders/glsl/distancefieldfonts/bitmap.vert deleted file mode 100644 index 1418d5c5..00000000 --- a/shaders/glsl/distancefieldfonts/bitmap.vert +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; -} ubo; - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = inUV; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/distancefieldfonts/bitmap.vert.spv b/shaders/glsl/distancefieldfonts/bitmap.vert.spv deleted file mode 100644 index 0872996a..00000000 Binary files a/shaders/glsl/distancefieldfonts/bitmap.vert.spv and /dev/null differ diff --git a/shaders/glsl/distancefieldfonts/sdf.frag b/shaders/glsl/distancefieldfonts/sdf.frag deleted file mode 100644 index d161ebe1..00000000 --- a/shaders/glsl/distancefieldfonts/sdf.frag +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 outlineColor; - float outlineWidth; - float outline; -} ubo; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - float distance = texture(samplerColor, inUV).a; - float smoothWidth = fwidth(distance); - float alpha = smoothstep(0.5 - smoothWidth, 0.5 + smoothWidth, distance); - vec3 rgb = vec3(alpha); - - if (ubo.outline > 0.0) - { - float w = 1.0 - ubo.outlineWidth; - alpha = smoothstep(w - smoothWidth, w + smoothWidth, distance); - rgb += mix(vec3(alpha), ubo.outlineColor.rgb, alpha); - } - - outFragColor = vec4(rgb, alpha); - -} \ No newline at end of file diff --git a/shaders/glsl/distancefieldfonts/sdf.frag.spv b/shaders/glsl/distancefieldfonts/sdf.frag.spv deleted file mode 100644 index 6230e0a7..00000000 Binary files a/shaders/glsl/distancefieldfonts/sdf.frag.spv and /dev/null differ diff --git a/shaders/glsl/distancefieldfonts/sdf.vert b/shaders/glsl/distancefieldfonts/sdf.vert deleted file mode 100644 index b09e4cf9..00000000 --- a/shaders/glsl/distancefieldfonts/sdf.vert +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 outlineColor; - float outlineWidth; - float outline; -} ubo; - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = inUV; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/distancefieldfonts/sdf.vert.spv b/shaders/glsl/distancefieldfonts/sdf.vert.spv deleted file mode 100644 index 076d2c2c..00000000 Binary files a/shaders/glsl/distancefieldfonts/sdf.vert.spv and /dev/null differ diff --git a/shaders/glsl/dynamicrendering/texture.frag b/shaders/glsl/dynamicrendering/texture.frag deleted file mode 100644 index 22553532..00000000 --- a/shaders/glsl/dynamicrendering/texture.frag +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -layout (set = 1, binding = 0) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec4 color = texture(samplerColor, inUV); - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a; - - outFragColor = vec4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/dynamicrendering/texture.frag.spv b/shaders/glsl/dynamicrendering/texture.frag.spv deleted file mode 100644 index 1ab597cc..00000000 Binary files a/shaders/glsl/dynamicrendering/texture.frag.spv and /dev/null differ diff --git a/shaders/glsl/dynamicrendering/texture.vert b/shaders/glsl/dynamicrendering/texture.vert deleted file mode 100644 index 3c7c17eb..00000000 --- a/shaders/glsl/dynamicrendering/texture.vert +++ /dev/null @@ -1,33 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 viewPos; -} ubo; - -layout (location = 0) out vec2 outUV; -layout (location = 1) out vec3 outNormal; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - outUV = inUV; - - vec3 worldPos = vec3(ubo.model * vec4(inPos, 1.0)); - - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(inverse(transpose(ubo.model))) * inNormal; - vec3 lightPos = vec3(0.0); - vec3 lPos = mat3(ubo.model) * lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = ubo.viewPos.xyz - pos.xyz; -} diff --git a/shaders/glsl/dynamicrendering/texture.vert.spv b/shaders/glsl/dynamicrendering/texture.vert.spv deleted file mode 100644 index 1d7d8865..00000000 Binary files a/shaders/glsl/dynamicrendering/texture.vert.spv and /dev/null differ diff --git a/shaders/glsl/dynamicuniformbuffer/base.frag b/shaders/glsl/dynamicuniformbuffer/base.frag deleted file mode 100644 index cbf87013..00000000 --- a/shaders/glsl/dynamicuniformbuffer/base.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = vec4(inColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/dynamicuniformbuffer/base.frag.spv b/shaders/glsl/dynamicuniformbuffer/base.frag.spv deleted file mode 100644 index f67f2011..00000000 Binary files a/shaders/glsl/dynamicuniformbuffer/base.frag.spv and /dev/null differ diff --git a/shaders/glsl/dynamicuniformbuffer/base.vert b/shaders/glsl/dynamicuniformbuffer/base.vert deleted file mode 100644 index acf87fec..00000000 --- a/shaders/glsl/dynamicuniformbuffer/base.vert +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inColor; - -layout (binding = 0) uniform UboView -{ - mat4 projection; - mat4 view; -} uboView; - -layout (binding = 1) uniform UboInstance -{ - mat4 model; -} uboInstance; - -layout (location = 0) out vec3 outColor; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outColor = inColor; - mat4 modelView = uboView.view * uboInstance.model; - vec3 worldPos = vec3(modelView * vec4(inPos, 1.0)); - gl_Position = uboView.projection * modelView * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/dynamicuniformbuffer/base.vert.spv b/shaders/glsl/dynamicuniformbuffer/base.vert.spv deleted file mode 100644 index 840e5277..00000000 Binary files a/shaders/glsl/dynamicuniformbuffer/base.vert.spv and /dev/null differ diff --git a/shaders/glsl/gears/gears.frag b/shaders/glsl/gears/gears.frag deleted file mode 100644 index 1795af76..00000000 --- a/shaders/glsl/gears/gears.frag +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inEyePos; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 Eye = normalize(-inEyePos); - vec3 Reflected = normalize(reflect(-inLightVec, inNormal)); - - vec4 IAmbient = vec4(0.2, 0.2, 0.2, 1.0); - vec4 IDiffuse = vec4(0.5, 0.5, 0.5, 0.5) * max(dot(inNormal, inLightVec), 0.0); - float specular = 0.25; - vec4 ISpecular = vec4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 0.8) * specular; - - outFragColor = vec4((IAmbient + IDiffuse) * vec4(inColor, 1.0) + ISpecular); -} \ No newline at end of file diff --git a/shaders/glsl/gears/gears.frag.spv b/shaders/glsl/gears/gears.frag.spv deleted file mode 100644 index 8d979893..00000000 Binary files a/shaders/glsl/gears/gears.frag.spv and /dev/null differ diff --git a/shaders/glsl/gears/gears.vert b/shaders/glsl/gears/gears.vert deleted file mode 100644 index d0799d1d..00000000 --- a/shaders/glsl/gears/gears.vert +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - vec4 lightpos; - mat4 model[3]; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outEyePos; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - outNormal = normalize(mat3x3(ubo.model[gl_InstanceIndex]) * inNormal); - outColor = inColor; - mat4 modelView = ubo.view * ubo.model[gl_InstanceIndex]; - vec4 pos = modelView * inPos; - outEyePos = vec3(modelView * pos); - vec4 lightPos = vec4(ubo.lightpos.xyz, 1.0) * modelView; - outLightVec = normalize(lightPos.xyz - outEyePos); - gl_Position = ubo.projection * pos; -} \ No newline at end of file diff --git a/shaders/glsl/gears/gears.vert.spv b/shaders/glsl/gears/gears.vert.spv deleted file mode 100644 index 0c30fe6f..00000000 Binary files a/shaders/glsl/gears/gears.vert.spv and /dev/null differ diff --git a/shaders/glsl/geometryshader/base.frag b/shaders/glsl/geometryshader/base.frag deleted file mode 100644 index d1c41721..00000000 --- a/shaders/glsl/geometryshader/base.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; - -layout (location = 0) out vec4 outFragColor; - -void main(void) -{ - outFragColor = vec4(inColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/geometryshader/base.frag.spv b/shaders/glsl/geometryshader/base.frag.spv deleted file mode 100644 index 3ede302d..00000000 Binary files a/shaders/glsl/geometryshader/base.frag.spv and /dev/null differ diff --git a/shaders/glsl/geometryshader/base.vert b/shaders/glsl/geometryshader/base.vert deleted file mode 100644 index 99b5ebee..00000000 --- a/shaders/glsl/geometryshader/base.vert +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; - -layout (location = 0) out vec3 outNormal; - -void main(void) -{ - outNormal = inNormal; - gl_Position = vec4(inPos.xyz, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/geometryshader/base.vert.spv b/shaders/glsl/geometryshader/base.vert.spv deleted file mode 100644 index ce0c1682..00000000 Binary files a/shaders/glsl/geometryshader/base.vert.spv and /dev/null differ diff --git a/shaders/glsl/geometryshader/mesh.frag b/shaders/glsl/geometryshader/mesh.frag deleted file mode 100644 index aab33e1d..00000000 --- a/shaders/glsl/geometryshader/mesh.frag +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 ambient = vec3(0.1); - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); - outFragColor = vec4((ambient + diffuse) * inColor.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/geometryshader/mesh.frag.spv b/shaders/glsl/geometryshader/mesh.frag.spv deleted file mode 100644 index 896f10e6..00000000 Binary files a/shaders/glsl/geometryshader/mesh.frag.spv and /dev/null differ diff --git a/shaders/glsl/geometryshader/mesh.vert b/shaders/glsl/geometryshader/mesh.vert deleted file mode 100644 index 69047000..00000000 --- a/shaders/glsl/geometryshader/mesh.vert +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (set = 0, binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - gl_Position = ubo.projection * ubo.model * vec4(inPos, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(ubo.model) * inNormal; - - vec3 lightPos = vec3(1.0f, 1.0f, 1.0f); - outLightVec = lightPos.xyz - pos.xyz; - outViewVec = -pos.xyz; -} diff --git a/shaders/glsl/geometryshader/mesh.vert.spv b/shaders/glsl/geometryshader/mesh.vert.spv deleted file mode 100644 index 136c49ee..00000000 Binary files a/shaders/glsl/geometryshader/mesh.vert.spv and /dev/null differ diff --git a/shaders/glsl/geometryshader/normaldebug.geom b/shaders/glsl/geometryshader/normaldebug.geom deleted file mode 100644 index beafe6ef..00000000 --- a/shaders/glsl/geometryshader/normaldebug.geom +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -layout (triangles) in; -layout (line_strip, max_vertices = 6) out; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; -} ubo; - -layout (location = 0) in vec3 inNormal[]; - -layout (location = 0) out vec3 outColor; - -void main(void) -{ - float normalLength = 0.02; - for(int i=0; i 0.98) - color = inColor * 1.5; - else if (intensity > 0.9) - color = inColor * 1.0; - else if (intensity > 0.5) - color = inColor * 0.6; - else if (intensity > 0.25) - color = inColor * 0.4; - else - color = inColor * 0.2; - outFragColor.rgb = color; - break; - } - case 2: // No shading - { - outFragColor.rgb = inColor; - break; - } - case 3: // Greyscale - { - outFragColor.rgb = vec3(dot(inColor.rgb, vec3(0.299, 0.587, 0.114))); - break; - } - } - - // Scene is dark, brigthen up a bit - outFragColor.rgb *= 1.25; -} \ No newline at end of file diff --git a/shaders/glsl/graphicspipelinelibrary/uber.frag.spv b/shaders/glsl/graphicspipelinelibrary/uber.frag.spv deleted file mode 100644 index 3131246c..00000000 Binary files a/shaders/glsl/graphicspipelinelibrary/uber.frag.spv and /dev/null differ diff --git a/shaders/glsl/hdr/bloom.frag b/shaders/glsl/hdr/bloom.frag deleted file mode 100644 index c3bf402b..00000000 --- a/shaders/glsl/hdr/bloom.frag +++ /dev/null @@ -1,63 +0,0 @@ -#version 450 - -layout (binding = 0) uniform sampler2D samplerColor0; -layout (binding = 1) uniform sampler2D samplerColor1; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outColor; - -layout (constant_id = 0) const int dir = 0; - -void main(void) -{ - // From the OpenGL Super bible - const float weights[] = float[](0.0024499299678342, - 0.0043538453346397, - 0.0073599963704157, - 0.0118349786570722, - 0.0181026699707781, - 0.0263392293891488, - 0.0364543006660986, - 0.0479932050577658, - 0.0601029809166942, - 0.0715974486241365, - 0.0811305381519717, - 0.0874493212267511, - 0.0896631113333857, - 0.0874493212267511, - 0.0811305381519717, - 0.0715974486241365, - 0.0601029809166942, - 0.0479932050577658, - 0.0364543006660986, - 0.0263392293891488, - 0.0181026699707781, - 0.0118349786570722, - 0.0073599963704157, - 0.0043538453346397, - 0.0024499299678342); - - - const float blurScale = 0.003; - const float blurStrength = 1.0; - - float ar = 1.0; - // Aspect ratio for vertical blur pass - if (dir == 1) - { - vec2 ts = textureSize(samplerColor1, 0); - ar = ts.y / ts.x; - } - - vec2 P = inUV.yx - vec2(0, (weights.length() >> 1) * ar * blurScale); - - vec4 color = vec4(0.0); - for (int i = 0; i < weights.length(); i++) - { - vec2 dv = vec2(0.0, i * blurScale) * ar; - color += texture(samplerColor1, P + dv) * weights[i] * blurStrength; - } - - outColor = color; -} \ No newline at end of file diff --git a/shaders/glsl/hdr/bloom.frag.spv b/shaders/glsl/hdr/bloom.frag.spv deleted file mode 100644 index 65e7d382..00000000 Binary files a/shaders/glsl/hdr/bloom.frag.spv and /dev/null differ diff --git a/shaders/glsl/hdr/bloom.vert b/shaders/glsl/hdr/bloom.vert deleted file mode 100644 index a5d60d0e..00000000 --- a/shaders/glsl/hdr/bloom.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/hdr/bloom.vert.spv b/shaders/glsl/hdr/bloom.vert.spv deleted file mode 100644 index ffcd1a84..00000000 Binary files a/shaders/glsl/hdr/bloom.vert.spv and /dev/null differ diff --git a/shaders/glsl/hdr/composition.frag b/shaders/glsl/hdr/composition.frag deleted file mode 100644 index 27f2a5f2..00000000 --- a/shaders/glsl/hdr/composition.frag +++ /dev/null @@ -1,13 +0,0 @@ -#version 450 - -layout (binding = 0) uniform sampler2D samplerColor0; -layout (binding = 1) uniform sampler2D samplerColor1; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outColor; - -void main() -{ - outColor = texture(samplerColor0, inUV); -} \ No newline at end of file diff --git a/shaders/glsl/hdr/composition.frag.spv b/shaders/glsl/hdr/composition.frag.spv deleted file mode 100644 index 1a334e0e..00000000 Binary files a/shaders/glsl/hdr/composition.frag.spv and /dev/null differ diff --git a/shaders/glsl/hdr/composition.vert b/shaders/glsl/hdr/composition.vert deleted file mode 100644 index 3a42f3c5..00000000 --- a/shaders/glsl/hdr/composition.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/hdr/composition.vert.spv b/shaders/glsl/hdr/composition.vert.spv deleted file mode 100644 index ffcd1a84..00000000 Binary files a/shaders/glsl/hdr/composition.vert.spv and /dev/null differ diff --git a/shaders/glsl/hdr/gbuffer.frag b/shaders/glsl/hdr/gbuffer.frag deleted file mode 100644 index e713fe36..00000000 --- a/shaders/glsl/hdr/gbuffer.frag +++ /dev/null @@ -1,93 +0,0 @@ -#version 450 - -layout (binding = 1) uniform samplerCube samplerEnvMap; - -layout (binding = 0) uniform UBO { - mat4 projection; - mat4 modelview; - mat4 inverseModelview; - float exposure; -} ubo; - -layout (location = 0) in vec3 inUVW; -layout (location = 1) in vec3 inPos; -layout (location = 2) in vec3 inNormal; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outColor0; -layout (location = 1) out vec4 outColor1; - -layout (constant_id = 0) const int type = 0; - -#define PI 3.1415926 -#define TwoPI (2.0 * PI) - -void main() -{ - vec4 color; - vec3 wcNormal; - - switch (type) { - case 0: // Skybox - { - vec3 normal = normalize(inUVW); - color = texture(samplerEnvMap, normal); - } - break; - - case 1: // Reflect - { - vec3 wViewVec = mat3(ubo.inverseModelview) * normalize(inViewVec); - vec3 normal = normalize(inNormal); - vec3 wNormal = mat3(ubo.inverseModelview) * normal; - - float NdotL = max(dot(normal, inLightVec), 0.0); - - vec3 eyeDir = normalize(inViewVec); - vec3 halfVec = normalize(inLightVec + eyeDir); - float NdotH = max(dot(normal, halfVec), 0.0); - float NdotV = max(dot(normal, eyeDir), 0.0); - float VdotH = max(dot(eyeDir, halfVec), 0.0); - - // Geometric attenuation - float NH2 = 2.0 * NdotH; - float g1 = (NH2 * NdotV) / VdotH; - float g2 = (NH2 * NdotL) / VdotH; - float geoAtt = min(1.0, min(g1, g2)); - - const float F0 = 0.6; - const float k = 0.2; - - // Fresnel (schlick approximation) - float fresnel = pow(1.0 - VdotH, 5.0); - fresnel *= (1.0 - F0); - fresnel += F0; - - float spec = (fresnel * geoAtt) / (NdotV * NdotL * 3.14); - - color = texture(samplerEnvMap, reflect(-wViewVec, wNormal)); - - color = vec4(color.rgb * NdotL * (k + spec * (1.0 - k)), 1.0); - } - break; - - case 2: // Refract - { - vec3 wViewVec = mat3(ubo.inverseModelview) * normalize(inViewVec); - vec3 wNormal = mat3(ubo.inverseModelview) * inNormal; - color = texture(samplerEnvMap, refract(-wViewVec, wNormal, 1.0/1.6)); - } - break; - } - - - // Color with manual exposure into attachment 0 - outColor0.rgb = vec3(1.0) - exp(-color.rgb * ubo.exposure); - - // Bright parts for bloom into attachment 1 - float l = dot(outColor0.rgb, vec3(0.2126, 0.7152, 0.0722)); - float threshold = 0.75; - outColor1.rgb = (l > threshold) ? outColor0.rgb : vec3(0.0); - outColor1.a = 1.0; -} \ No newline at end of file diff --git a/shaders/glsl/hdr/gbuffer.frag.spv b/shaders/glsl/hdr/gbuffer.frag.spv deleted file mode 100644 index d06577dc..00000000 Binary files a/shaders/glsl/hdr/gbuffer.frag.spv and /dev/null differ diff --git a/shaders/glsl/hdr/gbuffer.vert b/shaders/glsl/hdr/gbuffer.vert deleted file mode 100644 index 7a6ecc52..00000000 --- a/shaders/glsl/hdr/gbuffer.vert +++ /dev/null @@ -1,41 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; - -layout (constant_id = 0) const int type = 0; - -layout (binding = 0) uniform UBO { - mat4 projection; - mat4 modelview; - mat4 inverseModelview; - float exposure; -} ubo; - -layout (location = 0) out vec3 outUVW; -layout (location = 1) out vec3 outPos; -layout (location = 2) out vec3 outNormal; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -void main() -{ - outUVW = inPos; - - switch(type) { - case 0: // Skybox - outPos = vec3(mat3(ubo.modelview) * inPos); - gl_Position = vec4(ubo.projection * vec4(outPos, 1.0)); - break; - case 1: // Object - outPos = vec3(ubo.modelview * vec4(inPos, 1.0)); - gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0); - break; - } - outPos = vec3(ubo.modelview * vec4(inPos, 1.0)); - outNormal = mat3(ubo.modelview) * inNormal; - - vec3 lightPos = vec3(0.0f, -5.0f, 5.0f); - outLightVec = lightPos.xyz - outPos.xyz; - outViewVec = -outPos.xyz; -} diff --git a/shaders/glsl/hdr/gbuffer.vert.spv b/shaders/glsl/hdr/gbuffer.vert.spv deleted file mode 100644 index 30b2e9b8..00000000 Binary files a/shaders/glsl/hdr/gbuffer.vert.spv and /dev/null differ diff --git a/shaders/glsl/indirectdraw/ground.frag b/shaders/glsl/indirectdraw/ground.frag deleted file mode 100644 index 92f2048b..00000000 --- a/shaders/glsl/indirectdraw/ground.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (binding = 2) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/glsl/indirectdraw/ground.frag.spv b/shaders/glsl/indirectdraw/ground.frag.spv deleted file mode 100644 index 905e4653..00000000 Binary files a/shaders/glsl/indirectdraw/ground.frag.spv and /dev/null differ diff --git a/shaders/glsl/indirectdraw/ground.vert b/shaders/glsl/indirectdraw/ground.vert deleted file mode 100644 index b1aa82e6..00000000 --- a/shaders/glsl/indirectdraw/ground.vert +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -// Vertex attributes -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; -} ubo; - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = inUV * 32.0; - gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/indirectdraw/ground.vert.spv b/shaders/glsl/indirectdraw/ground.vert.spv deleted file mode 100644 index da1441ed..00000000 Binary files a/shaders/glsl/indirectdraw/ground.vert.spv and /dev/null differ diff --git a/shaders/glsl/indirectdraw/indirectdraw.frag b/shaders/glsl/indirectdraw/indirectdraw.frag deleted file mode 100644 index acdea70a..00000000 --- a/shaders/glsl/indirectdraw/indirectdraw.frag +++ /dev/null @@ -1,27 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2DArray samplerArray; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inUV; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec4 color = texture(samplerArray, inUV); - - if (color.a < 0.5) - { - discard; - } - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 ambient = vec3(0.65); - vec3 diffuse = max(dot(N, L), 0.0) * inColor; - outFragColor = vec4((ambient + diffuse) * color.rgb, 1.0); -} diff --git a/shaders/glsl/indirectdraw/indirectdraw.frag.spv b/shaders/glsl/indirectdraw/indirectdraw.frag.spv deleted file mode 100644 index cc4c82a4..00000000 Binary files a/shaders/glsl/indirectdraw/indirectdraw.frag.spv and /dev/null differ diff --git a/shaders/glsl/indirectdraw/indirectdraw.vert b/shaders/glsl/indirectdraw/indirectdraw.vert deleted file mode 100644 index ce081731..00000000 --- a/shaders/glsl/indirectdraw/indirectdraw.vert +++ /dev/null @@ -1,73 +0,0 @@ -#version 450 - -// Vertex attributes -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -// Instanced attributes -layout (location = 4) in vec3 instancePos; -layout (location = 5) in vec3 instanceRot; -layout (location = 6) in float instanceScale; -layout (location = 7) in int instanceTexIndex; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outUV; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -void main() -{ - outColor = inColor; - outUV = vec3(inUV, instanceTexIndex); - - mat4 mx, my, mz; - - // rotate around x - float s = sin(instanceRot.x); - float c = cos(instanceRot.x); - - mx[0] = vec4(c, s, 0.0, 0.0); - mx[1] = vec4(-s, c, 0.0, 0.0); - mx[2] = vec4(0.0, 0.0, 1.0, 0.0); - mx[3] = vec4(0.0, 0.0, 0.0, 1.0); - - // rotate around y - s = sin(instanceRot.y); - c = cos(instanceRot.y); - - my[0] = vec4(c, 0.0, s, 0.0); - my[1] = vec4(0.0, 1.0, 0.0, 0.0); - my[2] = vec4(-s, 0.0, c, 0.0); - my[3] = vec4(0.0, 0.0, 0.0, 1.0); - - // rot around z - s = sin(instanceRot.z); - c = cos(instanceRot.z); - - mz[0] = vec4(1.0, 0.0, 0.0, 0.0); - mz[1] = vec4(0.0, c, s, 0.0); - mz[2] = vec4(0.0, -s, c, 0.0); - mz[3] = vec4(0.0, 0.0, 0.0, 1.0); - - mat4 rotMat = mz * my * mx; - - outNormal = inNormal * mat3(rotMat); - - vec4 pos = vec4((inPos.xyz * instanceScale) + instancePos, 1.0) * rotMat; - - gl_Position = ubo.projection * ubo.modelview * pos; - - vec4 wPos = ubo.modelview * vec4(pos.xyz, 1.0); - vec4 lPos = vec4(0.0, -5.0, 0.0, 1.0); - outLightVec = lPos.xyz - pos.xyz; - outViewVec = -pos.xyz; -} diff --git a/shaders/glsl/indirectdraw/indirectdraw.vert.spv b/shaders/glsl/indirectdraw/indirectdraw.vert.spv deleted file mode 100644 index f2e2596f..00000000 Binary files a/shaders/glsl/indirectdraw/indirectdraw.vert.spv and /dev/null differ diff --git a/shaders/glsl/indirectdraw/skysphere.frag b/shaders/glsl/indirectdraw/skysphere.frag deleted file mode 100644 index 349e02e1..00000000 --- a/shaders/glsl/indirectdraw/skysphere.frag +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (binding = 2) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - const vec4 gradientStart = vec4(0.93, 0.9, 0.81, 1.0); - const vec4 gradientEnd = vec4(0.35, 0.5, 1.0, 1.0); - outFragColor = mix(gradientStart, gradientEnd, min(0.5 - (inUV.t + 0.05), 0.5)/0.15 + 0.5); -} \ No newline at end of file diff --git a/shaders/glsl/indirectdraw/skysphere.frag.spv b/shaders/glsl/indirectdraw/skysphere.frag.spv deleted file mode 100644 index bdb5e3db..00000000 Binary files a/shaders/glsl/indirectdraw/skysphere.frag.spv and /dev/null differ diff --git a/shaders/glsl/indirectdraw/skysphere.vert b/shaders/glsl/indirectdraw/skysphere.vert deleted file mode 100644 index c45acc99..00000000 --- a/shaders/glsl/indirectdraw/skysphere.vert +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -// Vertex attributes -layout (location = 0) in vec4 inPos; -layout (location = 2) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; -} ubo; - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = inUV; - // Skysphere always at center, only use rotation part of modelview matrix - gl_Position = ubo.projection * mat4(mat3(ubo.modelview)) * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/indirectdraw/skysphere.vert.spv b/shaders/glsl/indirectdraw/skysphere.vert.spv deleted file mode 100644 index d889ea21..00000000 Binary files a/shaders/glsl/indirectdraw/skysphere.vert.spv and /dev/null differ diff --git a/shaders/glsl/inlineuniformblocks/pbr.frag b/shaders/glsl/inlineuniformblocks/pbr.frag deleted file mode 100644 index 6c237e76..00000000 --- a/shaders/glsl/inlineuniformblocks/pbr.frag +++ /dev/null @@ -1,116 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inWorldPos; -layout (location = 1) in vec3 inNormal; - -layout (set = 0, binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - vec3 camPos; -} ubo; - -// Inline uniform block -layout (set = 1, binding = 0) uniform UniformInline { - float roughness; - float metallic; - float r; - float g; - float b; - float ambient; -} material; - -layout (location = 0) out vec4 outColor; - -const float PI = 3.14159265359; - -vec3 materialcolor() -{ - return vec3(material.r, material.g, material.b); -} - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -vec3 F_Schlick(float cosTheta, float metallic) -{ - vec3 F0 = mix(vec3(0.04), materialcolor(), metallic); // * material.specular - vec3 F = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); - return F; -} - -// Specular BRDF composition -------------------------------------------- - -vec3 BRDF(vec3 L, vec3 V, vec3 N, float metallic, float roughness) -{ - // Precalculate vectors and dot products - vec3 H = normalize (V + L); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - float dotLH = clamp(dot(L, H), 0.0, 1.0); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - - // Light color fixed - vec3 lightColor = vec3(1.0); - - vec3 color = vec3(0.0); - - if (dotNL > 0.0) - { - float rroughness = max(0.05, roughness); - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, rroughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, rroughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - vec3 F = F_Schlick(dotNV, metallic); - - vec3 spec = D * F * G / (4.0 * dotNL * dotNV); - - color += spec * dotNL * lightColor; - } - - return color; -} - -// ---------------------------------------------------------------------------- -void main() -{ - vec3 N = normalize(inNormal); - vec3 V = normalize(ubo.camPos - inWorldPos); - - float roughness = material.roughness; - - // Specular contribution - vec3 lightPos = vec3(0.0f, 0.0f, 10.0f); - vec3 Lo = vec3(0.0); - vec3 L = normalize(lightPos.xyz - inWorldPos); - Lo += BRDF(L, V, N, material.metallic, roughness); - - // Combine with ambient - vec3 color = materialcolor() * material.ambient; - color += Lo; - - // Gamma correct - color = pow(color, vec3(0.4545)); - - outColor = vec4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/inlineuniformblocks/pbr.frag.spv b/shaders/glsl/inlineuniformblocks/pbr.frag.spv deleted file mode 100644 index ce5ec66d..00000000 Binary files a/shaders/glsl/inlineuniformblocks/pbr.frag.spv and /dev/null differ diff --git a/shaders/glsl/inlineuniformblocks/pbr.vert b/shaders/glsl/inlineuniformblocks/pbr.vert deleted file mode 100644 index 8edb8b24..00000000 --- a/shaders/glsl/inlineuniformblocks/pbr.vert +++ /dev/null @@ -1,27 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; - -layout (set = 0, binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - vec3 camPos; -} ubo; - -layout (location = 0) out vec3 outWorldPos; -layout (location = 1) out vec3 outNormal; - -layout(push_constant) uniform PushConsts { - vec3 objPos; -} pushConsts; - -void main() -{ - vec3 locPos = vec3(ubo.model * vec4(inPos, 1.0)); - outWorldPos = locPos + pushConsts.objPos; - outNormal = mat3(ubo.model) * inNormal; - gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0); -} diff --git a/shaders/glsl/inlineuniformblocks/pbr.vert.spv b/shaders/glsl/inlineuniformblocks/pbr.vert.spv deleted file mode 100644 index ee516818..00000000 Binary files a/shaders/glsl/inlineuniformblocks/pbr.vert.spv and /dev/null differ diff --git a/shaders/glsl/inputattachments/attachmentread.frag b/shaders/glsl/inputattachments/attachmentread.frag deleted file mode 100644 index 685a619a..00000000 --- a/shaders/glsl/inputattachments/attachmentread.frag +++ /dev/null @@ -1,33 +0,0 @@ -#version 450 - -layout (input_attachment_index = 0, binding = 0) uniform subpassInput inputColor; -layout (input_attachment_index = 1, binding = 1) uniform subpassInput inputDepth; - -layout (binding = 2) uniform UBO { - vec2 brightnessContrast; - vec2 range; - int attachmentIndex; -} ubo; - -layout (location = 0) out vec4 outColor; - -vec3 brightnessContrast(vec3 color, float brightness, float contrast) { - return (color - 0.5) * contrast + 0.5 + brightness; -} - -void main() -{ - // Apply brightness and contrast filer to color input - if (ubo.attachmentIndex == 0) { - // Read color from previous color input attachment - vec3 color = subpassLoad(inputColor).rgb; - outColor.rgb = brightnessContrast(color, ubo.brightnessContrast[0], ubo.brightnessContrast[1]); - } - - // Visualize depth input range - if (ubo.attachmentIndex == 1) { - // Read depth from previous depth input attachment - float depth = subpassLoad(inputDepth).r; - outColor.rgb = vec3((depth - ubo.range[0]) * 1.0 / (ubo.range[1] - ubo.range[0])); - } -} \ No newline at end of file diff --git a/shaders/glsl/inputattachments/attachmentread.frag.spv b/shaders/glsl/inputattachments/attachmentread.frag.spv deleted file mode 100644 index 5c4575f4..00000000 Binary files a/shaders/glsl/inputattachments/attachmentread.frag.spv and /dev/null differ diff --git a/shaders/glsl/inputattachments/attachmentread.vert b/shaders/glsl/inputattachments/attachmentread.vert deleted file mode 100644 index d65ceaa5..00000000 --- a/shaders/glsl/inputattachments/attachmentread.vert +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -out gl_PerVertex { - vec4 gl_Position; -}; - -void main() -{ - gl_Position = vec4(vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2) * 2.0f - 1.0f, 0.0f, 1.0f); -} \ No newline at end of file diff --git a/shaders/glsl/inputattachments/attachmentread.vert.spv b/shaders/glsl/inputattachments/attachmentread.vert.spv deleted file mode 100644 index 3859ed6e..00000000 Binary files a/shaders/glsl/inputattachments/attachmentread.vert.spv and /dev/null differ diff --git a/shaders/glsl/inputattachments/attachmentwrite.frag b/shaders/glsl/inputattachments/attachmentwrite.frag deleted file mode 100644 index 69e1b6b7..00000000 --- a/shaders/glsl/inputattachments/attachmentwrite.frag +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outColor; - -void main() -{ - // Toon shading color attachment output - float intensity = dot(normalize(inNormal), normalize(inLightVec)); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - outColor.rgb = inColor * 3.0 * shade; - - // Depth attachment does not need to be explicitly written -} \ No newline at end of file diff --git a/shaders/glsl/inputattachments/attachmentwrite.frag.spv b/shaders/glsl/inputattachments/attachmentwrite.frag.spv deleted file mode 100644 index cfb4a18e..00000000 Binary files a/shaders/glsl/inputattachments/attachmentwrite.frag.spv and /dev/null differ diff --git a/shaders/glsl/inputattachments/attachmentwrite.vert b/shaders/glsl/inputattachments/attachmentwrite.vert deleted file mode 100644 index c5b82566..00000000 --- a/shaders/glsl/inputattachments/attachmentwrite.vert +++ /dev/null @@ -1,29 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inNormal; - -layout (binding = 0) uniform UBO { - mat4 projection; - mat4 model; - mat4 view; -} ubo; - -layout (location = 0) out vec3 outColor; -layout (location = 1) out vec3 outNormal; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -out gl_PerVertex { - vec4 gl_Position; -}; - -void main() -{ - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos, 1.0); - outColor = inColor; - outNormal = inNormal; - outLightVec = vec3(0.0f, 5.0f, 15.0f) - inPos; - outViewVec = -inPos.xyz; -} diff --git a/shaders/glsl/inputattachments/attachmentwrite.vert.spv b/shaders/glsl/inputattachments/attachmentwrite.vert.spv deleted file mode 100644 index 6a528305..00000000 Binary files a/shaders/glsl/inputattachments/attachmentwrite.vert.spv and /dev/null differ diff --git a/shaders/glsl/instancing/instancing.frag b/shaders/glsl/instancing/instancing.frag deleted file mode 100644 index 73beb4c2..00000000 --- a/shaders/glsl/instancing/instancing.frag +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2DArray samplerArray; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inUV; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec4 color = texture(samplerArray, inUV) * vec4(inColor, 1.0); - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.1) * inColor; - vec3 specular = (dot(N,L) > 0.0) ? pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75) * color.r : vec3(0.0); - outFragColor = vec4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/instancing/instancing.frag.spv b/shaders/glsl/instancing/instancing.frag.spv deleted file mode 100644 index 24392548..00000000 Binary files a/shaders/glsl/instancing/instancing.frag.spv and /dev/null differ diff --git a/shaders/glsl/instancing/instancing.vert b/shaders/glsl/instancing/instancing.vert deleted file mode 100644 index 78d750a6..00000000 --- a/shaders/glsl/instancing/instancing.vert +++ /dev/null @@ -1,81 +0,0 @@ -#version 450 - -// Vertex attributes -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -// Instanced attributes -layout (location = 4) in vec3 instancePos; -layout (location = 5) in vec3 instanceRot; -layout (location = 6) in float instanceScale; -layout (location = 7) in int instanceTexIndex; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec4 lightPos; - float locSpeed; - float globSpeed; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outUV; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -void main() -{ - outColor = inColor; - outUV = vec3(inUV, instanceTexIndex); - - mat3 mx, my, mz; - - // rotate around x - float s = sin(instanceRot.x + ubo.locSpeed); - float c = cos(instanceRot.x + ubo.locSpeed); - - mx[0] = vec3(c, s, 0.0); - mx[1] = vec3(-s, c, 0.0); - mx[2] = vec3(0.0, 0.0, 1.0); - - // rotate around y - s = sin(instanceRot.y + ubo.locSpeed); - c = cos(instanceRot.y + ubo.locSpeed); - - my[0] = vec3(c, 0.0, s); - my[1] = vec3(0.0, 1.0, 0.0); - my[2] = vec3(-s, 0.0, c); - - // rot around z - s = sin(instanceRot.z + ubo.locSpeed); - c = cos(instanceRot.z + ubo.locSpeed); - - mz[0] = vec3(1.0, 0.0, 0.0); - mz[1] = vec3(0.0, c, s); - mz[2] = vec3(0.0, -s, c); - - mat3 rotMat = mz * my * mx; - - mat4 gRotMat; - s = sin(instanceRot.y + ubo.globSpeed); - c = cos(instanceRot.y + ubo.globSpeed); - gRotMat[0] = vec4(c, 0.0, s, 0.0); - gRotMat[1] = vec4(0.0, 1.0, 0.0, 0.0); - gRotMat[2] = vec4(-s, 0.0, c, 0.0); - gRotMat[3] = vec4(0.0, 0.0, 0.0, 1.0); - - vec4 locPos = vec4(inPos.xyz * rotMat, 1.0); - vec4 pos = vec4((locPos.xyz * instanceScale) + instancePos, 1.0); - - gl_Position = ubo.projection * ubo.modelview * gRotMat * pos; - outNormal = mat3(ubo.modelview * gRotMat) * inverse(rotMat) * inNormal; - - pos = ubo.modelview * vec4(inPos.xyz + instancePos, 1.0); - vec3 lPos = mat3(ubo.modelview) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} diff --git a/shaders/glsl/instancing/instancing.vert.spv b/shaders/glsl/instancing/instancing.vert.spv deleted file mode 100644 index 4fe79ffc..00000000 Binary files a/shaders/glsl/instancing/instancing.vert.spv and /dev/null differ diff --git a/shaders/glsl/instancing/planet.frag b/shaders/glsl/instancing/planet.frag deleted file mode 100644 index 81926b90..00000000 --- a/shaders/glsl/instancing/planet.frag +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0) * 1.5; - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * inColor; - vec3 specular = pow(max(dot(R, V), 0.0), 4.0) * vec3(0.5) * color.r; - outFragColor = vec4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/instancing/planet.frag.spv b/shaders/glsl/instancing/planet.frag.spv deleted file mode 100644 index f6db777e..00000000 Binary files a/shaders/glsl/instancing/planet.frag.spv and /dev/null differ diff --git a/shaders/glsl/instancing/planet.vert b/shaders/glsl/instancing/planet.vert deleted file mode 100644 index 8638d23c..00000000 --- a/shaders/glsl/instancing/planet.vert +++ /dev/null @@ -1,32 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec2 outUV; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -void main() -{ - outColor = inColor; - outUV = inUV; - gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.modelview * vec4(inPos, 1.0); - outNormal = mat3(ubo.modelview) * inNormal; - vec3 lPos = mat3(ubo.modelview) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/instancing/planet.vert.spv b/shaders/glsl/instancing/planet.vert.spv deleted file mode 100644 index 80a8401f..00000000 Binary files a/shaders/glsl/instancing/planet.vert.spv and /dev/null differ diff --git a/shaders/glsl/instancing/starfield.frag b/shaders/glsl/instancing/starfield.frag deleted file mode 100644 index 87c53d82..00000000 --- a/shaders/glsl/instancing/starfield.frag +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inUVW; - -layout (location = 0) out vec4 outFragColor; - -#define HASHSCALE3 vec3(443.897, 441.423, 437.195) -#define STARFREQUENCY 0.01 - -// Hash function by Dave Hoskins (https://www.shadertoy.com/view/4djSRW) -float hash33(vec3 p3) -{ - p3 = fract(p3 * HASHSCALE3); - p3 += dot(p3, p3.yxz+vec3(19.19)); - return fract((p3.x + p3.y)*p3.z + (p3.x+p3.z)*p3.y + (p3.y+p3.z)*p3.x); -} - -vec3 starField(vec3 pos) -{ - vec3 color = vec3(0.0); - float threshhold = (1.0 - STARFREQUENCY); - float rnd = hash33(pos); - if (rnd >= threshhold) - { - float starCol = pow((rnd - threshhold) / (1.0 - threshhold), 16.0); - color += vec3(starCol); - } - return color; -} - -void main() -{ - outFragColor = vec4(starField(inUVW), 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/instancing/starfield.frag.spv b/shaders/glsl/instancing/starfield.frag.spv deleted file mode 100644 index 8b9dab3e..00000000 Binary files a/shaders/glsl/instancing/starfield.frag.spv and /dev/null differ diff --git a/shaders/glsl/instancing/starfield.vert b/shaders/glsl/instancing/starfield.vert deleted file mode 100644 index 381e249f..00000000 --- a/shaders/glsl/instancing/starfield.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) out vec3 outUVW; - -void main() -{ - outUVW = vec3((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUVW.st * 2.0f - 1.0f, 0.0f, 1.0f); -} \ No newline at end of file diff --git a/shaders/glsl/instancing/starfield.vert.spv b/shaders/glsl/instancing/starfield.vert.spv deleted file mode 100644 index 27b5ccbe..00000000 Binary files a/shaders/glsl/instancing/starfield.vert.spv and /dev/null differ diff --git a/shaders/glsl/meshshader/meshshader.frag b/shaders/glsl/meshshader/meshshader.frag deleted file mode 100644 index f425dd4c..00000000 --- a/shaders/glsl/meshshader/meshshader.frag +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (c) 2021, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 450 - -layout (location = 0) in VertexInput { - vec4 color; -} vertexInput; - -layout(location = 0) out vec4 outFragColor; - - -void main() -{ - outFragColor = vertexInput.color; -} \ No newline at end of file diff --git a/shaders/glsl/meshshader/meshshader.frag.spv b/shaders/glsl/meshshader/meshshader.frag.spv deleted file mode 100644 index 14a5c003..00000000 Binary files a/shaders/glsl/meshshader/meshshader.frag.spv and /dev/null differ diff --git a/shaders/glsl/meshshader/meshshader.mesh b/shaders/glsl/meshshader/meshshader.mesh deleted file mode 100644 index 2e0a34ce..00000000 --- a/shaders/glsl/meshshader/meshshader.mesh +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (c) 2021, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 450 -#extension GL_EXT_mesh_shader : require - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; -} ubo; - -layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; -layout(triangles, max_vertices = 3, max_primitives = 1) out; - -layout(location = 0) out VertexOutput -{ - vec4 color; -} vertexOutput[]; - -const vec4[3] positions = { - vec4( 0.0, -1.0, 0.0, 1.0), - vec4(-1.0, 1.0, 0.0, 1.0), - vec4( 1.0, 1.0, 0.0, 1.0) -}; - -const vec4[3] colors = { - vec4(0.0, 1.0, 0.0, 1.0), - vec4(0.0, 0.0, 1.0, 1.0), - vec4(1.0, 0.0, 0.0, 1.0) -}; - -void main() -{ - uint iid = gl_LocalInvocationID.x; - - vec4 offset = vec4(0.0, 0.0, gl_GlobalInvocationID.x, 0.0); - - SetMeshOutputsEXT(3, 1); - mat4 mvp = ubo.projection * ubo.view * ubo.model; - gl_MeshVerticesEXT[0].gl_Position = mvp * (positions[0] + offset); - gl_MeshVerticesEXT[1].gl_Position = mvp * (positions[1] + offset); - gl_MeshVerticesEXT[2].gl_Position = mvp * (positions[2] + offset); - vertexOutput[0].color = colors[0]; - vertexOutput[1].color = colors[1]; - vertexOutput[2].color = colors[2]; - gl_PrimitiveTriangleIndicesEXT[gl_LocalInvocationIndex] = uvec3(0, 1, 2); -} diff --git a/shaders/glsl/meshshader/meshshader.mesh.spv b/shaders/glsl/meshshader/meshshader.mesh.spv deleted file mode 100644 index d9dcb786..00000000 Binary files a/shaders/glsl/meshshader/meshshader.mesh.spv and /dev/null differ diff --git a/shaders/glsl/meshshader/meshshader.task b/shaders/glsl/meshshader/meshshader.task deleted file mode 100644 index 47439e91..00000000 --- a/shaders/glsl/meshshader/meshshader.task +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright (c) 2021, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 450 -#extension GL_EXT_mesh_shader : require - -void main() -{ - EmitMeshTasksEXT(3, 1, 1); -} diff --git a/shaders/glsl/meshshader/meshshader.task.spv b/shaders/glsl/meshshader/meshshader.task.spv deleted file mode 100644 index abcbc5df..00000000 Binary files a/shaders/glsl/meshshader/meshshader.task.spv and /dev/null differ diff --git a/shaders/glsl/multisampling/mesh.frag b/shaders/glsl/multisampling/mesh.frag deleted file mode 100644 index fb415cef..00000000 --- a/shaders/glsl/multisampling/mesh.frag +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -layout (set = 1, binding = 0) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0); - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.15) * inColor; - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); - outFragColor = vec4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/multisampling/mesh.frag.spv b/shaders/glsl/multisampling/mesh.frag.spv deleted file mode 100644 index 5cd56265..00000000 Binary files a/shaders/glsl/multisampling/mesh.frag.spv and /dev/null differ diff --git a/shaders/glsl/multisampling/mesh.vert b/shaders/glsl/multisampling/mesh.vert deleted file mode 100644 index 2e742bf1..00000000 --- a/shaders/glsl/multisampling/mesh.vert +++ /dev/null @@ -1,33 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -layout (set = 0, binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec2 outUV; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - outUV = inUV; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(ubo.model) * inNormal; - vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/multisampling/mesh.vert.spv b/shaders/glsl/multisampling/mesh.vert.spv deleted file mode 100644 index d96f3926..00000000 Binary files a/shaders/glsl/multisampling/mesh.vert.spv and /dev/null differ diff --git a/shaders/glsl/multithreading/phong.frag b/shaders/glsl/multithreading/phong.frag deleted file mode 100644 index 274cd063..00000000 --- a/shaders/glsl/multithreading/phong.frag +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * inColor; - vec3 specular = pow(max(dot(R, V), 0.0), 8.0) * vec3(0.75); - outFragColor = vec4(diffuse + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/multithreading/phong.frag.spv b/shaders/glsl/multithreading/phong.frag.spv deleted file mode 100644 index 31922bcb..00000000 Binary files a/shaders/glsl/multithreading/phong.frag.spv and /dev/null differ diff --git a/shaders/glsl/multithreading/phong.vert b/shaders/glsl/multithreading/phong.vert deleted file mode 100644 index a65a6b2b..00000000 --- a/shaders/glsl/multithreading/phong.vert +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (std140, push_constant) uniform PushConsts -{ - mat4 mvp; - vec3 color; -} pushConsts; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -void main() -{ - outNormal = inNormal; - - if ( (inColor.r == 1.0) && (inColor.g == 0.0) && (inColor.b == 0.0)) - { - outColor = pushConsts.color; - } - else - { - outColor = inColor; - } - - gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0); - - vec4 pos = pushConsts.mvp * vec4(inPos, 1.0); - outNormal = mat3(pushConsts.mvp) * inNormal; -// vec3 lPos = ubo.lightPos.xyz; -vec3 lPos = vec3(0.0); - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/multithreading/phong.vert.spv b/shaders/glsl/multithreading/phong.vert.spv deleted file mode 100644 index 84ca10a3..00000000 Binary files a/shaders/glsl/multithreading/phong.vert.spv and /dev/null differ diff --git a/shaders/glsl/multithreading/starsphere.frag b/shaders/glsl/multithreading/starsphere.frag deleted file mode 100644 index c61301f3..00000000 --- a/shaders/glsl/multithreading/starsphere.frag +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inUVW; - -layout (location = 0) out vec4 outFragColor; - -#define HASHSCALE3 vec3(443.897, 441.423, 437.195) -#define STARFREQUENCY 0.01 - -// Hash function by Dave Hoskins (https://www.shadertoy.com/view/4djSRW) -float hash33(vec3 p3) -{ - p3 = fract(p3 * HASHSCALE3); - p3 += dot(p3, p3.yxz+vec3(19.19)); - return fract((p3.x + p3.y)*p3.z + (p3.x+p3.z)*p3.y + (p3.y+p3.z)*p3.x); -} - -vec3 starField(vec3 pos) -{ - vec3 color = vec3(0.0); - float threshhold = (1.0 - STARFREQUENCY); - float rnd = hash33(pos); - if (rnd >= threshhold) - { - float starCol = pow((rnd - threshhold) / (1.0 - threshhold), 16.0); - color += vec3(starCol); - } - return color; -} - -void main() -{ - // Fake atmosphere at the bottom - vec3 atmosphere = clamp(vec3(0.1, 0.15, 0.4) * (inUVW.t + 0.25), 0.0, 1.0); - - vec3 color = starField(inUVW) + atmosphere; - - outFragColor = vec4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/multithreading/starsphere.frag.spv b/shaders/glsl/multithreading/starsphere.frag.spv deleted file mode 100644 index 6505ae2f..00000000 Binary files a/shaders/glsl/multithreading/starsphere.frag.spv and /dev/null differ diff --git a/shaders/glsl/multithreading/starsphere.vert b/shaders/glsl/multithreading/starsphere.vert deleted file mode 100644 index 3ff9b4b1..00000000 --- a/shaders/glsl/multithreading/starsphere.vert +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout (std140, push_constant) uniform PushConsts -{ - mat4 mvp; -} pushConsts; - -layout (location = 0) out vec3 outUVW; - -void main() -{ - outUVW = inPos; - gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/multithreading/starsphere.vert.spv b/shaders/glsl/multithreading/starsphere.vert.spv deleted file mode 100644 index 1a98a97a..00000000 Binary files a/shaders/glsl/multithreading/starsphere.vert.spv and /dev/null differ diff --git a/shaders/glsl/multiview/multiview.frag b/shaders/glsl/multiview/multiview.frag deleted file mode 100644 index 94d7f9a3..00000000 --- a/shaders/glsl/multiview/multiview.frag +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outColor; - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 ambient = vec3(0.1); - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); - outColor = vec4((ambient + diffuse) * inColor.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/multiview/multiview.frag.spv b/shaders/glsl/multiview/multiview.frag.spv deleted file mode 100644 index 1eae642c..00000000 Binary files a/shaders/glsl/multiview/multiview.frag.spv and /dev/null differ diff --git a/shaders/glsl/multiview/multiview.vert b/shaders/glsl/multiview/multiview.vert deleted file mode 100644 index 14a6dcc5..00000000 --- a/shaders/glsl/multiview/multiview.vert +++ /dev/null @@ -1,35 +0,0 @@ -#version 450 - -#extension GL_EXT_multiview : enable - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - - -layout (binding = 0) uniform UBO -{ - mat4 projection[2]; - mat4 modelview[2]; - vec4 lightPos; -} ubo; - -void main() -{ - outColor = inColor; - outNormal = mat3(ubo.modelview[gl_ViewIndex]) * inNormal; - - vec4 pos = vec4(inPos.xyz, 1.0); - vec4 worldPos = ubo.modelview[gl_ViewIndex] * pos; - - vec3 lPos = vec3(ubo.modelview[gl_ViewIndex] * ubo.lightPos); - outLightVec = lPos - worldPos.xyz; - outViewVec = -worldPos.xyz; - - gl_Position = ubo.projection[gl_ViewIndex] * worldPos; -} diff --git a/shaders/glsl/multiview/multiview.vert.spv b/shaders/glsl/multiview/multiview.vert.spv deleted file mode 100644 index d217329b..00000000 Binary files a/shaders/glsl/multiview/multiview.vert.spv and /dev/null differ diff --git a/shaders/glsl/multiview/viewdisplay.frag b/shaders/glsl/multiview/viewdisplay.frag deleted file mode 100644 index 0549b851..00000000 --- a/shaders/glsl/multiview/viewdisplay.frag +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2DArray samplerView; - -layout (binding = 0) uniform UBO -{ - layout(offset = 272) float distortionAlpha; -} ubo; - -layout (location = 0) in vec2 inUV; -layout (location = 0) out vec4 outColor; - -layout (constant_id = 0) const float VIEW_LAYER = 0.0f; - -void main() -{ - const float alpha = ubo.distortionAlpha; - - vec2 p1 = vec2(2.0 * inUV - 1.0); - vec2 p2 = p1 / (1.0 - alpha * length(p1)); - p2 = (p2 + 1.0) * 0.5; - - bool inside = ((p2.x >= 0.0) && (p2.x <= 1.0) && (p2.y >= 0.0 ) && (p2.y <= 1.0)); - outColor = inside ? texture(samplerView, vec3(p2, VIEW_LAYER)) : vec4(0.0); -} \ No newline at end of file diff --git a/shaders/glsl/multiview/viewdisplay.frag.spv b/shaders/glsl/multiview/viewdisplay.frag.spv deleted file mode 100644 index 474dfc48..00000000 Binary files a/shaders/glsl/multiview/viewdisplay.frag.spv and /dev/null differ diff --git a/shaders/glsl/multiview/viewdisplay.vert b/shaders/glsl/multiview/viewdisplay.vert deleted file mode 100644 index 3a42f3c5..00000000 --- a/shaders/glsl/multiview/viewdisplay.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/multiview/viewdisplay.vert.spv b/shaders/glsl/multiview/viewdisplay.vert.spv deleted file mode 100644 index 822048d7..00000000 Binary files a/shaders/glsl/multiview/viewdisplay.vert.spv and /dev/null differ diff --git a/shaders/glsl/negativeviewportheight/quad.frag b/shaders/glsl/negativeviewportheight/quad.frag deleted file mode 100644 index fb6b6322..00000000 --- a/shaders/glsl/negativeviewportheight/quad.frag +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 - -layout (binding = 0) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; -layout (location = 0) out vec4 outColor; - -void main() -{ - outColor = texture(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/glsl/negativeviewportheight/quad.frag.spv b/shaders/glsl/negativeviewportheight/quad.frag.spv deleted file mode 100644 index 30d62d65..00000000 Binary files a/shaders/glsl/negativeviewportheight/quad.frag.spv and /dev/null differ diff --git a/shaders/glsl/negativeviewportheight/quad.vert b/shaders/glsl/negativeviewportheight/quad.vert deleted file mode 100644 index a7febf5a..00000000 --- a/shaders/glsl/negativeviewportheight/quad.vert +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = inUV; - gl_Position = vec4(inPos, 1.0f); -} diff --git a/shaders/glsl/negativeviewportheight/quad.vert.spv b/shaders/glsl/negativeviewportheight/quad.vert.spv deleted file mode 100644 index c93f1261..00000000 Binary files a/shaders/glsl/negativeviewportheight/quad.vert.spv and /dev/null differ diff --git a/shaders/glsl/occlusionquery/mesh.frag b/shaders/glsl/occlusionquery/mesh.frag deleted file mode 100644 index 5755f10f..00000000 --- a/shaders/glsl/occlusionquery/mesh.frag +++ /dev/null @@ -1,28 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in float inVisible; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - - -void main() -{ - if (inVisible > 0.0) - { - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.25) * inColor; - vec3 specular = pow(max(dot(R, V), 0.0), 8.0) * vec3(0.75); - outFragColor = vec4(diffuse + specular, 1.0); - } - else - { - outFragColor = vec4(vec3(0.1), 1.0); - } -} \ No newline at end of file diff --git a/shaders/glsl/occlusionquery/mesh.frag.spv b/shaders/glsl/occlusionquery/mesh.frag.spv deleted file mode 100644 index a87b9dc5..00000000 Binary files a/shaders/glsl/occlusionquery/mesh.frag.spv and /dev/null differ diff --git a/shaders/glsl/occlusionquery/mesh.vert b/shaders/glsl/occlusionquery/mesh.vert deleted file mode 100644 index 031c1a41..00000000 --- a/shaders/glsl/occlusionquery/mesh.vert +++ /dev/null @@ -1,35 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 color; - vec4 lightPos; - float visible; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out float outVisible; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -void main() -{ - outNormal = inNormal; - outColor = inColor * ubo.color.rgb; - outVisible = ubo.visible; - - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(ubo.model) * inNormal; - outLightVec = ubo.lightPos.xyz - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/occlusionquery/mesh.vert.spv b/shaders/glsl/occlusionquery/mesh.vert.spv deleted file mode 100644 index ce4baf11..00000000 Binary files a/shaders/glsl/occlusionquery/mesh.vert.spv and /dev/null differ diff --git a/shaders/glsl/occlusionquery/occluder.frag b/shaders/glsl/occlusionquery/occluder.frag deleted file mode 100644 index e57001d8..00000000 --- a/shaders/glsl/occlusionquery/occluder.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = vec4(inColor, 0.5); -} \ No newline at end of file diff --git a/shaders/glsl/occlusionquery/occluder.frag.spv b/shaders/glsl/occlusionquery/occluder.frag.spv deleted file mode 100644 index baa4f841..00000000 Binary files a/shaders/glsl/occlusionquery/occluder.frag.spv and /dev/null differ diff --git a/shaders/glsl/occlusionquery/occluder.vert b/shaders/glsl/occlusionquery/occluder.vert deleted file mode 100644 index 558950df..00000000 --- a/shaders/glsl/occlusionquery/occluder.vert +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 color; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outColor; - -void main() -{ - outColor = inColor * ubo.color.rgb; - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/occlusionquery/occluder.vert.spv b/shaders/glsl/occlusionquery/occluder.vert.spv deleted file mode 100644 index dbc3b9fe..00000000 Binary files a/shaders/glsl/occlusionquery/occluder.vert.spv and /dev/null differ diff --git a/shaders/glsl/occlusionquery/simple.frag b/shaders/glsl/occlusionquery/simple.frag deleted file mode 100644 index e88b26af..00000000 --- a/shaders/glsl/occlusionquery/simple.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = vec4(1.0); -} \ No newline at end of file diff --git a/shaders/glsl/occlusionquery/simple.frag.spv b/shaders/glsl/occlusionquery/simple.frag.spv deleted file mode 100644 index 6dbf76f1..00000000 Binary files a/shaders/glsl/occlusionquery/simple.frag.spv and /dev/null differ diff --git a/shaders/glsl/occlusionquery/simple.vert b/shaders/glsl/occlusionquery/simple.vert deleted file mode 100644 index 0e193854..00000000 --- a/shaders/glsl/occlusionquery/simple.vert +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 color; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outColor; - -void main() -{ - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/occlusionquery/simple.vert.spv b/shaders/glsl/occlusionquery/simple.vert.spv deleted file mode 100644 index b6011ed3..00000000 Binary files a/shaders/glsl/occlusionquery/simple.vert.spv and /dev/null differ diff --git a/shaders/glsl/offscreen/mirror.frag b/shaders/glsl/offscreen/mirror.frag deleted file mode 100644 index faa75c59..00000000 --- a/shaders/glsl/offscreen/mirror.frag +++ /dev/null @@ -1,37 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (location = 0) in vec4 inPos; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec4 tmp = vec4(1.0 / inPos.w); - vec4 projCoord = inPos * tmp; - - // Scale and bias - projCoord += vec4(1.0); - projCoord *= vec4(0.5); - - // Slow single pass blur - // For demonstration purposes only - const float blurSize = 1.0 / 512.0; - - outFragColor = vec4(vec3(0.0), 1.); - - if (gl_FrontFacing) - { - // Only render mirrored scene on front facing (upper) side of mirror surface - vec4 reflection = vec4(0.0); - for (int x = -3; x <= 3; x++) - { - for (int y = -3; y <= 3; y++) - { - reflection += texture(samplerColor, vec2(projCoord.s + x * blurSize, projCoord.t + y * blurSize)) / 49.0; - } - } - outFragColor += reflection; - }; -} \ No newline at end of file diff --git a/shaders/glsl/offscreen/mirror.frag.spv b/shaders/glsl/offscreen/mirror.frag.spv deleted file mode 100644 index a94d88da..00000000 Binary files a/shaders/glsl/offscreen/mirror.frag.spv and /dev/null differ diff --git a/shaders/glsl/offscreen/mirror.vert b/shaders/glsl/offscreen/mirror.vert deleted file mode 100644 index f0941fad..00000000 --- a/shaders/glsl/offscreen/mirror.vert +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; -} ubo; - -layout (location = 0) out vec4 outPos; - -void main() -{ - outPos = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); - gl_Position = outPos; -} diff --git a/shaders/glsl/offscreen/mirror.vert.spv b/shaders/glsl/offscreen/mirror.vert.spv deleted file mode 100644 index 7a7977e3..00000000 Binary files a/shaders/glsl/offscreen/mirror.vert.spv and /dev/null differ diff --git a/shaders/glsl/offscreen/phong.frag b/shaders/glsl/offscreen/phong.frag deleted file mode 100644 index 7c26398d..00000000 --- a/shaders/glsl/offscreen/phong.frag +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inEyePos; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 Eye = normalize(-inEyePos); - vec3 Reflected = normalize(reflect(-inLightVec, inNormal)); - - vec4 IAmbient = vec4(0.1, 0.1, 0.1, 1.0); - vec4 IDiffuse = vec4(max(dot(inNormal, inLightVec), 0.0)); - float specular = 0.75; - vec4 ISpecular = vec4(0.0); - if (dot(inEyePos, inNormal) < 0.0) - { - ISpecular = vec4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 16.0) * specular; - } - - outFragColor = vec4((IAmbient + IDiffuse) * vec4(inColor, 1.0) + ISpecular); -} \ No newline at end of file diff --git a/shaders/glsl/offscreen/phong.frag.spv b/shaders/glsl/offscreen/phong.frag.spv deleted file mode 100644 index 8c26766f..00000000 Binary files a/shaders/glsl/offscreen/phong.frag.spv and /dev/null differ diff --git a/shaders/glsl/offscreen/phong.vert b/shaders/glsl/offscreen/phong.vert deleted file mode 100644 index f540ea69..00000000 --- a/shaders/glsl/offscreen/phong.vert +++ /dev/null @@ -1,31 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outEyePos; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos, 1.0); - outEyePos = vec3(ubo.view * ubo.model * vec4(inPos, 1.0)); - outLightVec = normalize(ubo.lightPos.xyz - outEyePos); - - // Clip against reflection plane - vec4 clipPlane = vec4(0.0, 0.0, 0.0, 0.0); - gl_ClipDistance[0] = dot(vec4(inPos, 1.0), clipPlane); -} diff --git a/shaders/glsl/offscreen/phong.vert.spv b/shaders/glsl/offscreen/phong.vert.spv deleted file mode 100644 index 05af386e..00000000 Binary files a/shaders/glsl/offscreen/phong.vert.spv and /dev/null differ diff --git a/shaders/glsl/offscreen/quad.frag b/shaders/glsl/offscreen/quad.frag deleted file mode 100644 index 108e89b0..00000000 --- a/shaders/glsl/offscreen/quad.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/glsl/offscreen/quad.frag.spv b/shaders/glsl/offscreen/quad.frag.spv deleted file mode 100644 index 03440f7c..00000000 Binary files a/shaders/glsl/offscreen/quad.frag.spv and /dev/null differ diff --git a/shaders/glsl/offscreen/quad.vert b/shaders/glsl/offscreen/quad.vert deleted file mode 100644 index 3a42f3c5..00000000 --- a/shaders/glsl/offscreen/quad.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/offscreen/quad.vert.spv b/shaders/glsl/offscreen/quad.vert.spv deleted file mode 100644 index 5683fcb3..00000000 Binary files a/shaders/glsl/offscreen/quad.vert.spv and /dev/null differ diff --git a/shaders/glsl/oit/color.frag b/shaders/glsl/oit/color.frag deleted file mode 100644 index 06a53080..00000000 --- a/shaders/glsl/oit/color.frag +++ /dev/null @@ -1,56 +0,0 @@ -#version 450 - -#define MAX_FRAGMENT_COUNT 128 - -struct Node -{ - vec4 color; - float depth; - uint next; -}; - -layout (location = 0) out vec4 outFragColor; - -layout (set = 0, binding = 0, r32ui) uniform uimage2D headIndexImage; - -layout (set = 0, binding = 1) buffer LinkedListSBO -{ - Node nodes[]; -}; - -void main() -{ - Node fragments[MAX_FRAGMENT_COUNT]; - int count = 0; - - uint nodeIdx = imageLoad(headIndexImage, ivec2(gl_FragCoord.xy)).r; - - while (nodeIdx != 0xffffffff && count < MAX_FRAGMENT_COUNT) - { - fragments[count] = nodes[nodeIdx]; - nodeIdx = fragments[count].next; - ++count; - } - - // Do the insertion sort - for (uint i = 1; i < count; ++i) - { - Node insert = fragments[i]; - uint j = i; - while (j > 0 && insert.depth > fragments[j - 1].depth) - { - fragments[j] = fragments[j-1]; - --j; - } - fragments[j] = insert; - } - - // Do blending - vec4 color = vec4(0.025, 0.025, 0.025, 1.0f); - for (int i = 0; i < count; ++i) - { - color = mix(color, fragments[i].color, fragments[i].color.a); - } - - outFragColor = color; -} \ No newline at end of file diff --git a/shaders/glsl/oit/color.frag.spv b/shaders/glsl/oit/color.frag.spv deleted file mode 100644 index 8b5d3670..00000000 Binary files a/shaders/glsl/oit/color.frag.spv and /dev/null differ diff --git a/shaders/glsl/oit/color.vert b/shaders/glsl/oit/color.vert deleted file mode 100644 index ccfa5756..00000000 --- a/shaders/glsl/oit/color.vert +++ /dev/null @@ -1,7 +0,0 @@ -#version 450 - -void main() -{ - vec2 uv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(uv * 2.0f + -1.0f, 0.0f, 1.0f); -} \ No newline at end of file diff --git a/shaders/glsl/oit/color.vert.spv b/shaders/glsl/oit/color.vert.spv deleted file mode 100644 index b24b3211..00000000 Binary files a/shaders/glsl/oit/color.vert.spv and /dev/null differ diff --git a/shaders/glsl/oit/geometry.frag b/shaders/glsl/oit/geometry.frag deleted file mode 100644 index 17c143fc..00000000 --- a/shaders/glsl/oit/geometry.frag +++ /dev/null @@ -1,46 +0,0 @@ -#version 450 - -layout (early_fragment_tests) in; - -struct Node -{ - vec4 color; - float depth; - uint next; -}; - -layout (set = 0, binding = 1) buffer GeometrySBO -{ - uint count; - uint maxNodeCount; -}; - -layout (set = 0, binding = 2, r32ui) uniform coherent uimage2D headIndexImage; - -layout (set = 0, binding = 3) buffer LinkedListSBO -{ - Node nodes[]; -}; - -layout(push_constant) uniform PushConsts { - mat4 model; - vec4 color; -} pushConsts; - -void main() -{ - // Increase the node count - uint nodeIdx = atomicAdd(count, 1); - - // Check LinkedListSBO is full - if (nodeIdx < maxNodeCount) - { - // Exchange new head index and previous head index - uint prevHeadIdx = imageAtomicExchange(headIndexImage, ivec2(gl_FragCoord.xy), nodeIdx); - - // Store node data - nodes[nodeIdx].color = pushConsts.color; - nodes[nodeIdx].depth = gl_FragCoord.z; - nodes[nodeIdx].next = prevHeadIdx; - } -} \ No newline at end of file diff --git a/shaders/glsl/oit/geometry.frag.spv b/shaders/glsl/oit/geometry.frag.spv deleted file mode 100644 index 7e861318..00000000 Binary files a/shaders/glsl/oit/geometry.frag.spv and /dev/null differ diff --git a/shaders/glsl/oit/geometry.vert b/shaders/glsl/oit/geometry.vert deleted file mode 100644 index e53b0c75..00000000 --- a/shaders/glsl/oit/geometry.vert +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout (set = 0, binding = 0) uniform RenderPassUBO -{ - mat4 projection; - mat4 view; -} renderPassUBO; - -layout(push_constant) uniform PushConsts { - mat4 model; - vec4 color; -} pushConsts; - -void main() -{ - mat4 PVM = renderPassUBO.projection * renderPassUBO.view * pushConsts.model; - gl_Position = PVM * vec4(inPos, 1.0); -} diff --git a/shaders/glsl/oit/geometry.vert.spv b/shaders/glsl/oit/geometry.vert.spv deleted file mode 100644 index 1784d170..00000000 Binary files a/shaders/glsl/oit/geometry.vert.spv and /dev/null differ diff --git a/shaders/glsl/parallaxmapping/parallax.frag b/shaders/glsl/parallaxmapping/parallax.frag deleted file mode 100644 index f7cbbdb1..00000000 --- a/shaders/glsl/parallaxmapping/parallax.frag +++ /dev/null @@ -1,109 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D sColorMap; -layout (binding = 2) uniform sampler2D sNormalHeightMap; - -layout (binding = 3) uniform UBO -{ - float heightScale; - float parallaxBias; - float numLayers; - int mappingMode; -} ubo; - -layout (location = 0) in vec2 inUV; -layout (location = 1) in vec3 inTangentLightPos; -layout (location = 2) in vec3 inTangentViewPos; -layout (location = 3) in vec3 inTangentFragPos; - -layout (location = 0) out vec4 outColor; - -vec2 parallaxMapping(vec2 uv, vec3 viewDir) -{ - float height = 1.0 - textureLod(sNormalHeightMap, uv, 0.0).a; - vec2 p = viewDir.xy * (height * (ubo.heightScale * 0.5) + ubo.parallaxBias) / viewDir.z; - return uv - p; -} - -vec2 steepParallaxMapping(vec2 uv, vec3 viewDir) -{ - float layerDepth = 1.0 / ubo.numLayers; - float currLayerDepth = 0.0; - vec2 deltaUV = viewDir.xy * ubo.heightScale / (viewDir.z * ubo.numLayers); - vec2 currUV = uv; - float height = 1.0 - textureLod(sNormalHeightMap, currUV, 0.0).a; - for (int i = 0; i < ubo.numLayers; i++) { - currLayerDepth += layerDepth; - currUV -= deltaUV; - height = 1.0 - textureLod(sNormalHeightMap, currUV, 0.0).a; - if (height < currLayerDepth) { - break; - } - } - return currUV; -} - -vec2 parallaxOcclusionMapping(vec2 uv, vec3 viewDir) -{ - float layerDepth = 1.0 / ubo.numLayers; - float currLayerDepth = 0.0; - vec2 deltaUV = viewDir.xy * ubo.heightScale / (viewDir.z * ubo.numLayers); - vec2 currUV = uv; - float height = 1.0 - textureLod(sNormalHeightMap, currUV, 0.0).a; - for (int i = 0; i < ubo.numLayers; i++) { - currLayerDepth += layerDepth; - currUV -= deltaUV; - height = 1.0 - textureLod(sNormalHeightMap, currUV, 0.0).a; - if (height < currLayerDepth) { - break; - } - } - vec2 prevUV = currUV + deltaUV; - float nextDepth = height - currLayerDepth; - float prevDepth = 1.0 - textureLod(sNormalHeightMap, prevUV, 0.0).a - currLayerDepth + layerDepth; - return mix(currUV, prevUV, nextDepth / (nextDepth - prevDepth)); -} - -void main(void) -{ - vec3 V = normalize(inTangentViewPos - inTangentFragPos); - vec2 uv = inUV; - - if (ubo.mappingMode == 0) { - // Color only - outColor = texture(sColorMap, inUV); - } else { - switch(ubo.mappingMode) { - case 2: - uv = parallaxMapping(inUV, V); - break; - case 3: - uv = steepParallaxMapping(inUV, V); - break; - case 4: - uv = parallaxOcclusionMapping(inUV, V); - break; - } - - // Perform sampling before (potentially) discarding. - // This is to avoid implicit derivatives in non-uniform control flow. - vec3 normalHeightMapLod = textureLod(sNormalHeightMap, uv, 0.0).rgb; - vec3 color = texture(sColorMap, uv).rgb; - - // Discard fragments at texture border - if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) { - discard; - } - - vec3 N = normalize(normalHeightMapLod * 2.0 - 1.0); - vec3 L = normalize(inTangentLightPos - inTangentFragPos); - vec3 R = reflect(-L, N); - vec3 H = normalize(L + V); - - vec3 ambient = 0.2 * color; - vec3 diffuse = max(dot(L, N), 0.0) * color; - vec3 specular = vec3(0.15) * pow(max(dot(N, H), 0.0), 32.0); - - outColor = vec4(ambient + diffuse + specular, 1.0f); - } -} diff --git a/shaders/glsl/parallaxmapping/parallax.frag.spv b/shaders/glsl/parallaxmapping/parallax.frag.spv deleted file mode 100644 index f591ae65..00000000 Binary files a/shaders/glsl/parallaxmapping/parallax.frag.spv and /dev/null differ diff --git a/shaders/glsl/parallaxmapping/parallax.vert b/shaders/glsl/parallaxmapping/parallax.vert deleted file mode 100644 index 5ceb6b22..00000000 --- a/shaders/glsl/parallaxmapping/parallax.vert +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inNormal; -layout (location = 3) in vec4 inTangent; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 lightPos; - vec4 cameraPos; -} ubo; - -layout (location = 0) out vec2 outUV; -layout (location = 1) out vec3 outTangentLightPos; -layout (location = 2) out vec3 outTangentViewPos; -layout (location = 3) out vec3 outTangentFragPos; - -void main(void) -{ - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos, 1.0f); - outTangentFragPos = vec3(ubo.model * vec4(inPos, 1.0)); - outUV = inUV; - - vec3 N = normalize(mat3(ubo.model) * inNormal); - vec3 T = normalize(mat3(ubo.model) * inTangent.xyz); - vec3 B = normalize(cross(N, T)); - mat3 TBN = transpose(mat3(T, B, N)); - - outTangentLightPos = TBN * ubo.lightPos.xyz; - outTangentViewPos = TBN * ubo.cameraPos.xyz; - outTangentFragPos = TBN * outTangentFragPos; -} diff --git a/shaders/glsl/parallaxmapping/parallax.vert.spv b/shaders/glsl/parallaxmapping/parallax.vert.spv deleted file mode 100644 index 2ffdfc7f..00000000 Binary files a/shaders/glsl/parallaxmapping/parallax.vert.spv and /dev/null differ diff --git a/shaders/glsl/particlesystem/normalmap.frag b/shaders/glsl/particlesystem/normalmap.frag deleted file mode 100644 index 34acfee7..00000000 --- a/shaders/glsl/particlesystem/normalmap.frag +++ /dev/null @@ -1,41 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D sColorMap; -layout (binding = 2) uniform sampler2D sNormalHeightMap; - -#define lightRadius 45.0 - -layout (location = 0) in vec2 inUV; -layout (location = 1) in vec3 inLightVec; -layout (location = 2) in vec3 inLightVecB; -layout (location = 3) in vec3 inLightDir; -layout (location = 4) in vec3 inViewVec; - -layout (location = 0) out vec4 outFragColor; - -void main(void) -{ - vec3 specularColor = vec3(0.85, 0.5, 0.0); - - float invRadius = 1.0/lightRadius; - float ambient = 0.25; - - vec3 rgb, normal; - - rgb = texture(sColorMap, inUV).rgb; - normal = normalize((texture(sNormalHeightMap, inUV).rgb - 0.5) * 2.0); - - float distSqr = dot(inLightVecB, inLightVecB); - vec3 lVec = inLightVecB * inversesqrt(distSqr); - - float atten = max(clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0), ambient); - float diffuse = clamp(dot(lVec, normal), 0.0, 1.0); - - vec3 light = normalize(-inLightVec); - vec3 view = normalize(inViewVec); - vec3 reflectDir = reflect(-light, normal); - - float specular = pow(max(dot(view, reflectDir), 0.0), 4.0); - - outFragColor = vec4((rgb * atten + (diffuse * rgb + 0.5 * specular * specularColor.rgb)) * atten, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/particlesystem/normalmap.frag.spv b/shaders/glsl/particlesystem/normalmap.frag.spv deleted file mode 100644 index 9bd9a4a2..00000000 Binary files a/shaders/glsl/particlesystem/normalmap.frag.spv and /dev/null differ diff --git a/shaders/glsl/particlesystem/normalmap.vert b/shaders/glsl/particlesystem/normalmap.vert deleted file mode 100644 index d57a26fa..00000000 --- a/shaders/glsl/particlesystem/normalmap.vert +++ /dev/null @@ -1,50 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inNormal; -layout (location = 3) in vec4 inTangent; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 normal; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec2 outUV; -layout (location = 1) out vec3 outLightVec; -layout (location = 2) out vec3 outLightVecB; -layout (location = 3) out vec3 outLightDir; -layout (location = 4) out vec3 outViewVec; - -void main(void) -{ - vec3 vertexPosition = vec3(ubo.model * vec4(inPos, 1.0)); - outLightDir = normalize(ubo.lightPos.xyz - vertexPosition); - - vec3 biTangent = cross(inNormal, inTangent.xyz); - - // Setup (t)angent-(b)inormal-(n)ormal matrix for converting - // object coordinates into tangent space - mat3 tbnMatrix; - tbnMatrix[0] = mat3(ubo.normal) * inTangent.xyz; - tbnMatrix[1] = mat3(ubo.normal) * biTangent; - tbnMatrix[2] = mat3(ubo.normal) * inNormal; - - outLightVec.xyz = vec3(ubo.lightPos.xyz - vertexPosition) * tbnMatrix; - - vec3 lightDist = ubo.lightPos.xyz - inPos; - outLightVecB.x = dot(inTangent.xyz, lightDist); - outLightVecB.y = dot(biTangent, lightDist); - outLightVecB.z = dot(inNormal, lightDist); - - outViewVec.x = dot(inTangent.xyz, inPos); - outViewVec.y = dot(biTangent, inPos); - outViewVec.z = dot(inNormal, inPos); - - outUV = inUV; - - gl_Position = ubo.projection * ubo.model * vec4(inPos, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/particlesystem/normalmap.vert.spv b/shaders/glsl/particlesystem/normalmap.vert.spv deleted file mode 100644 index a2904765..00000000 Binary files a/shaders/glsl/particlesystem/normalmap.vert.spv and /dev/null differ diff --git a/shaders/glsl/particlesystem/particle.frag b/shaders/glsl/particlesystem/particle.frag deleted file mode 100644 index 1aa29c5e..00000000 --- a/shaders/glsl/particlesystem/particle.frag +++ /dev/null @@ -1,42 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerSmoke; -layout (binding = 2) uniform sampler2D samplerFire; - -layout (location = 0) in vec4 inColor; -layout (location = 1) in float inAlpha; -layout (location = 2) in flat int inType; -layout (location = 3) in float inRotation; - -layout (location = 0) out vec4 outFragColor; - -void main () -{ - vec4 color; - float alpha = (inAlpha <= 1.0) ? inAlpha : 2.0 - inAlpha; - - // Rotate texture coordinates - // Rotate UV - float rotCenter = 0.5; - float rotCos = cos(inRotation); - float rotSin = sin(inRotation); - vec2 rotUV = vec2( - rotCos * (gl_PointCoord.x - rotCenter) + rotSin * (gl_PointCoord.y - rotCenter) + rotCenter, - rotCos * (gl_PointCoord.y - rotCenter) - rotSin * (gl_PointCoord.x - rotCenter) + rotCenter); - - - if (inType == 0) - { - // Flame - color = texture(samplerFire, rotUV); - outFragColor.a = 0.0; - } - else - { - // Smoke - color = texture(samplerSmoke, rotUV); - outFragColor.a = color.a * alpha; - } - - outFragColor.rgb = color.rgb * inColor.rgb * alpha; -} \ No newline at end of file diff --git a/shaders/glsl/particlesystem/particle.frag.spv b/shaders/glsl/particlesystem/particle.frag.spv deleted file mode 100644 index 21fe3f05..00000000 Binary files a/shaders/glsl/particlesystem/particle.frag.spv and /dev/null differ diff --git a/shaders/glsl/particlesystem/particle.vert b/shaders/glsl/particlesystem/particle.vert deleted file mode 100644 index f504ab0b..00000000 --- a/shaders/glsl/particlesystem/particle.vert +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec4 inColor; -layout (location = 2) in float inAlpha; -layout (location = 3) in float inSize; -layout (location = 4) in float inRotation; -layout (location = 5) in int inType; - -layout (location = 0) out vec4 outColor; -layout (location = 1) out float outAlpha; -layout (location = 2) out flat int outType; -layout (location = 3) out float outRotation; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec2 viewportDim; - float pointSize; -} ubo; - -void main () -{ - outColor = inColor; - outAlpha = inAlpha; - outType = inType; - outRotation = inRotation; - - gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0); - - // Base size of the point sprites - float spriteSize = 8.0 * inSize; - - // Scale particle size depending on camera projection - vec4 eyePos = ubo.modelview * vec4(inPos.xyz, 1.0); - vec4 projectedCorner = ubo.projection * vec4(0.5 * spriteSize, 0.5 * spriteSize, eyePos.z, eyePos.w); - gl_PointSize = ubo.viewportDim.x * projectedCorner.x / projectedCorner.w; -} \ No newline at end of file diff --git a/shaders/glsl/particlesystem/particle.vert.spv b/shaders/glsl/particlesystem/particle.vert.spv deleted file mode 100644 index d04e22ac..00000000 Binary files a/shaders/glsl/particlesystem/particle.vert.spv and /dev/null differ diff --git a/shaders/glsl/pbrbasic/pbr.frag b/shaders/glsl/pbrbasic/pbr.frag deleted file mode 100644 index 8896cbcb..00000000 --- a/shaders/glsl/pbrbasic/pbr.frag +++ /dev/null @@ -1,126 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inWorldPos; -layout (location = 1) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - vec3 camPos; -} ubo; - -layout (binding = 1) uniform UBOShared { - vec4 lights[4]; -} uboParams; - -layout (location = 0) out vec4 outColor; - -layout(push_constant) uniform PushConsts { - layout(offset = 12) float roughness; - layout(offset = 16) float metallic; - layout(offset = 20) float r; - layout(offset = 24) float g; - layout(offset = 28) float b; -} material; - -const float PI = 3.14159265359; - -//#define ROUGHNESS_PATTERN 1 - -vec3 materialcolor() -{ - return vec3(material.r, material.g, material.b); -} - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -vec3 F_Schlick(float cosTheta, float metallic) -{ - vec3 F0 = mix(vec3(0.04), materialcolor(), metallic); // * material.specular - vec3 F = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); - return F; -} - -// Specular BRDF composition -------------------------------------------- - -vec3 BRDF(vec3 L, vec3 V, vec3 N, float metallic, float roughness) -{ - // Precalculate vectors and dot products - vec3 H = normalize (V + L); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - float dotLH = clamp(dot(L, H), 0.0, 1.0); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - - // Light color fixed - vec3 lightColor = vec3(1.0); - - vec3 color = vec3(0.0); - - if (dotNL > 0.0) - { - float rroughness = max(0.05, roughness); - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, roughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, rroughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - vec3 F = F_Schlick(dotNV, metallic); - - vec3 spec = D * F * G / (4.0 * dotNL * dotNV); - - color += spec * dotNL * lightColor; - } - - return color; -} - -// ---------------------------------------------------------------------------- -void main() -{ - vec3 N = normalize(inNormal); - vec3 V = normalize(ubo.camPos - inWorldPos); - - float roughness = material.roughness; - - // Add striped pattern to roughness based on vertex position -#ifdef ROUGHNESS_PATTERN - roughness = max(roughness, step(fract(inWorldPos.y * 2.02), 0.5)); -#endif - - // Specular contribution - vec3 Lo = vec3(0.0); - for (int i = 0; i < uboParams.lights.length(); i++) { - vec3 L = normalize(uboParams.lights[i].xyz - inWorldPos); - Lo += BRDF(L, V, N, material.metallic, roughness); - }; - - // Combine with ambient - vec3 color = materialcolor() * 0.02; - color += Lo; - - // Gamma correct - color = pow(color, vec3(0.4545)); - - outColor = vec4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pbrbasic/pbr.frag.spv b/shaders/glsl/pbrbasic/pbr.frag.spv deleted file mode 100644 index 657ca772..00000000 Binary files a/shaders/glsl/pbrbasic/pbr.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbrbasic/pbr.vert b/shaders/glsl/pbrbasic/pbr.vert deleted file mode 100644 index 709f12bf..00000000 --- a/shaders/glsl/pbrbasic/pbr.vert +++ /dev/null @@ -1,32 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - vec3 camPos; -} ubo; - -layout (location = 0) out vec3 outWorldPos; -layout (location = 1) out vec3 outNormal; - -layout(push_constant) uniform PushConsts { - vec3 objPos; -} pushConsts; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - vec3 locPos = vec3(ubo.model * vec4(inPos, 1.0)); - outWorldPos = locPos + pushConsts.objPos; - outNormal = mat3(ubo.model) * inNormal; - gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0); -} diff --git a/shaders/glsl/pbrbasic/pbr.vert.spv b/shaders/glsl/pbrbasic/pbr.vert.spv deleted file mode 100644 index 84274aa1..00000000 Binary files a/shaders/glsl/pbrbasic/pbr.vert.spv and /dev/null differ diff --git a/shaders/glsl/pbribl/filtercube.vert b/shaders/glsl/pbribl/filtercube.vert deleted file mode 100644 index 1226e28e..00000000 --- a/shaders/glsl/pbribl/filtercube.vert +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout(push_constant) uniform PushConsts { - layout (offset = 0) mat4 mvp; -} pushConsts; - -layout (location = 0) out vec3 outUVW; - -out gl_PerVertex { - vec4 gl_Position; -}; - -void main() -{ - outUVW = inPos; - gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/pbribl/filtercube.vert.spv b/shaders/glsl/pbribl/filtercube.vert.spv deleted file mode 100644 index 220a3df4..00000000 Binary files a/shaders/glsl/pbribl/filtercube.vert.spv and /dev/null differ diff --git a/shaders/glsl/pbribl/genbrdflut.frag b/shaders/glsl/pbribl/genbrdflut.frag deleted file mode 100644 index d3aba88b..00000000 --- a/shaders/glsl/pbribl/genbrdflut.frag +++ /dev/null @@ -1,90 +0,0 @@ -#version 450 - -layout (location = 0) in vec2 inUV; -layout (location = 0) out vec4 outColor; -layout (constant_id = 0) const uint NUM_SAMPLES = 1024u; - -const float PI = 3.1415926536; - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(vec2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,vec2(a,b)); - float sn= mod(dt,3.14); - return fract(sin(sn) * c); -} - -vec2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return vec2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 tangentX = normalize(cross(up, normal)); - vec3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Geometric Shadowing function -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float k = (roughness * roughness) / 2.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -vec2 BRDF(float NoV, float roughness) -{ - // Normal always points along z-axis for the 2D lookup - const vec3 N = vec3(0.0, 0.0, 1.0); - vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV); - - vec2 LUT = vec2(0.0); - for(uint i = 0u; i < NUM_SAMPLES; i++) { - vec2 Xi = hammersley2d(i, NUM_SAMPLES); - vec3 H = importanceSample_GGX(Xi, roughness, N); - vec3 L = 2.0 * dot(V, H) * H - V; - - float dotNL = max(dot(N, L), 0.0); - float dotNV = max(dot(N, V), 0.0); - float dotVH = max(dot(V, H), 0.0); - float dotNH = max(dot(H, N), 0.0); - - if (dotNL > 0.0) { - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - float G_Vis = (G * dotVH) / (dotNH * dotNV); - float Fc = pow(1.0 - dotVH, 5.0); - LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis); - } - } - return LUT / float(NUM_SAMPLES); -} - -void main() -{ - outColor = vec4(BRDF(inUV.s, inUV.t), 0.0, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pbribl/genbrdflut.frag.spv b/shaders/glsl/pbribl/genbrdflut.frag.spv deleted file mode 100644 index f83c5e38..00000000 Binary files a/shaders/glsl/pbribl/genbrdflut.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbribl/genbrdflut.vert b/shaders/glsl/pbribl/genbrdflut.vert deleted file mode 100644 index f3dd2335..00000000 --- a/shaders/glsl/pbribl/genbrdflut.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} \ No newline at end of file diff --git a/shaders/glsl/pbribl/genbrdflut.vert.spv b/shaders/glsl/pbribl/genbrdflut.vert.spv deleted file mode 100644 index fc2b37dd..00000000 Binary files a/shaders/glsl/pbribl/genbrdflut.vert.spv and /dev/null differ diff --git a/shaders/glsl/pbribl/irradiancecube.frag b/shaders/glsl/pbribl/irradiancecube.frag deleted file mode 100644 index 3232db48..00000000 --- a/shaders/glsl/pbribl/irradiancecube.frag +++ /dev/null @@ -1,37 +0,0 @@ -// Generates an irradiance cube from an environment map using convolution - -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 0) out vec4 outColor; -layout (binding = 0) uniform samplerCube samplerEnv; - -layout(push_constant) uniform PushConsts { - layout (offset = 64) float deltaPhi; - layout (offset = 68) float deltaTheta; -} consts; - -#define PI 3.1415926535897932384626433832795 - -void main() -{ - vec3 N = normalize(inPos); - vec3 up = vec3(0.0, 1.0, 0.0); - vec3 right = normalize(cross(up, N)); - up = cross(N, right); - - const float TWO_PI = PI * 2.0; - const float HALF_PI = PI * 0.5; - - vec3 color = vec3(0.0); - uint sampleCount = 0u; - for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) { - for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) { - vec3 tempVec = cos(phi) * right + sin(phi) * up; - vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec; - color += texture(samplerEnv, sampleVector).rgb * cos(theta) * sin(theta); - sampleCount++; - } - } - outColor = vec4(PI * color / float(sampleCount), 1.0); -} diff --git a/shaders/glsl/pbribl/irradiancecube.frag.spv b/shaders/glsl/pbribl/irradiancecube.frag.spv deleted file mode 100644 index a369970e..00000000 Binary files a/shaders/glsl/pbribl/irradiancecube.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbribl/pbribl.frag b/shaders/glsl/pbribl/pbribl.frag deleted file mode 100644 index 568e09a9..00000000 --- a/shaders/glsl/pbribl/pbribl.frag +++ /dev/null @@ -1,162 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inWorldPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (binding = 0) uniform UBO { - mat4 projection; - mat4 model; - mat4 view; - vec3 camPos; -} ubo; - -layout (binding = 1) uniform UBOParams { - vec4 lights[4]; - float exposure; - float gamma; -} uboParams; - -layout(push_constant) uniform PushConsts { - layout(offset = 12) float roughness; - layout(offset = 16) float metallic; - layout(offset = 20) float specular; - layout(offset = 24) float r; - layout(offset = 28) float g; - layout(offset = 32) float b; -} material; - -layout (binding = 2) uniform samplerCube samplerIrradiance; -layout (binding = 3) uniform sampler2D samplerBRDFLUT; -layout (binding = 4) uniform samplerCube prefilteredMap; - -layout (location = 0) out vec4 outColor; - -#define PI 3.1415926535897932384626433832795 -#define ALBEDO vec3(material.r, material.g, material.b) - -// From http://filmicgames.com/archives/75 -vec3 Uncharted2Tonemap(vec3 x) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F; -} - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -vec3 F_Schlick(float cosTheta, vec3 F0) -{ - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} -vec3 F_SchlickR(float cosTheta, vec3 F0, float roughness) -{ - return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); -} - -vec3 prefilteredReflection(vec3 R, float roughness) -{ - const float MAX_REFLECTION_LOD = 9.0; // todo: param/const - float lod = roughness * MAX_REFLECTION_LOD; - float lodf = floor(lod); - float lodc = ceil(lod); - vec3 a = textureLod(prefilteredMap, R, lodf).rgb; - vec3 b = textureLod(prefilteredMap, R, lodc).rgb; - return mix(a, b, lod - lodf); -} - -vec3 specularContribution(vec3 L, vec3 V, vec3 N, vec3 F0, float metallic, float roughness) -{ - // Precalculate vectors and dot products - vec3 H = normalize (V + L); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - - // Light color fixed - vec3 lightColor = vec3(1.0); - - vec3 color = vec3(0.0); - - if (dotNL > 0.0) { - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, roughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - vec3 F = F_Schlick(dotNV, F0); - vec3 spec = D * F * G / (4.0 * dotNL * dotNV + 0.001); - vec3 kD = (vec3(1.0) - F) * (1.0 - metallic); - color += (kD * ALBEDO / PI + spec) * dotNL; - } - - return color; -} - -void main() -{ - vec3 N = normalize(inNormal); - vec3 V = normalize(ubo.camPos - inWorldPos); - vec3 R = reflect(-V, N); - - float metallic = material.metallic; - float roughness = material.roughness; - - vec3 F0 = vec3(0.04); - F0 = mix(F0, ALBEDO, metallic); - - vec3 Lo = vec3(0.0); - for(int i = 0; i < uboParams.lights.length(); i++) { - vec3 L = normalize(uboParams.lights[i].xyz - inWorldPos); - Lo += specularContribution(L, V, N, F0, metallic, roughness); - } - - vec2 brdf = texture(samplerBRDFLUT, vec2(max(dot(N, V), 0.0), roughness)).rg; - vec3 reflection = prefilteredReflection(R, roughness).rgb; - vec3 irradiance = texture(samplerIrradiance, N).rgb; - - // Diffuse based on irradiance - vec3 diffuse = irradiance * ALBEDO; - - vec3 F = F_SchlickR(max(dot(N, V), 0.0), F0, roughness); - - // Specular reflectance - vec3 specular = reflection * (F * brdf.x + brdf.y); - - // Ambient part - vec3 kD = 1.0 - F; - kD *= 1.0 - metallic; - vec3 ambient = (kD * diffuse + specular); - - vec3 color = ambient + Lo; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap(vec3(11.2f))); - // Gamma correction - color = pow(color, vec3(1.0f / uboParams.gamma)); - - outColor = vec4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pbribl/pbribl.frag.spv b/shaders/glsl/pbribl/pbribl.frag.spv deleted file mode 100644 index 4573e23d..00000000 Binary files a/shaders/glsl/pbribl/pbribl.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbribl/pbribl.vert b/shaders/glsl/pbribl/pbribl.vert deleted file mode 100644 index a287a833..00000000 --- a/shaders/glsl/pbribl/pbribl.vert +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - vec3 camPos; -} ubo; - -layout (location = 0) out vec3 outWorldPos; -layout (location = 1) out vec3 outNormal; -layout (location = 2) out vec2 outUV; - -layout(push_constant) uniform PushConsts { - vec3 objPos; -} pushConsts; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - vec3 locPos = vec3(ubo.model * vec4(inPos, 1.0)); - outWorldPos = locPos + pushConsts.objPos; - outNormal = mat3(ubo.model) * inNormal; - outUV = inUV; - outUV.t = 1.0 - inUV.t; - gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0); -} diff --git a/shaders/glsl/pbribl/pbribl.vert.spv b/shaders/glsl/pbribl/pbribl.vert.spv deleted file mode 100644 index 37d92b7b..00000000 Binary files a/shaders/glsl/pbribl/pbribl.vert.spv and /dev/null differ diff --git a/shaders/glsl/pbribl/prefilterenvmap.frag b/shaders/glsl/pbribl/prefilterenvmap.frag deleted file mode 100644 index ae1212ed..00000000 --- a/shaders/glsl/pbribl/prefilterenvmap.frag +++ /dev/null @@ -1,105 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 0) out vec4 outColor; - -layout (binding = 0) uniform samplerCube samplerEnv; - -layout(push_constant) uniform PushConsts { - layout (offset = 64) float roughness; - layout (offset = 68) uint numSamples; -} consts; - -const float PI = 3.1415926536; - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(vec2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,vec2(a,b)); - float sn= mod(dt,3.14); - return fract(sin(sn) * c); -} - -vec2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return vec2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 tangentX = normalize(cross(up, normal)); - vec3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Normal Distribution function -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -vec3 prefilterEnvMap(vec3 R, float roughness) -{ - vec3 N = R; - vec3 V = R; - vec3 color = vec3(0.0); - float totalWeight = 0.0; - float envMapDim = float(textureSize(samplerEnv, 0).s); - for(uint i = 0u; i < consts.numSamples; i++) { - vec2 Xi = hammersley2d(i, consts.numSamples); - vec3 H = importanceSample_GGX(Xi, roughness, N); - vec3 L = 2.0 * dot(V, H) * H - V; - float dotNL = clamp(dot(N, L), 0.0, 1.0); - if(dotNL > 0.0) { - // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ - - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotVH = clamp(dot(V, H), 0.0, 1.0); - - // Probability Distribution Function - float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; - // Slid angle of current smple - float omegaS = 1.0 / (float(consts.numSamples) * pdf); - // Solid angle of 1 pixel across all cube faces - float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); - // Biased (+1.0) mip level for better result - float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); - color += textureLod(samplerEnv, L, mipLevel).rgb * dotNL; - totalWeight += dotNL; - - } - } - return (color / totalWeight); -} - - -void main() -{ - vec3 N = normalize(inPos); - outColor = vec4(prefilterEnvMap(N, consts.roughness), 1.0); -} diff --git a/shaders/glsl/pbribl/prefilterenvmap.frag.spv b/shaders/glsl/pbribl/prefilterenvmap.frag.spv deleted file mode 100644 index aa5955dc..00000000 Binary files a/shaders/glsl/pbribl/prefilterenvmap.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbribl/skybox.frag b/shaders/glsl/pbribl/skybox.frag deleted file mode 100644 index e46fdfe0..00000000 --- a/shaders/glsl/pbribl/skybox.frag +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (binding = 2) uniform samplerCube samplerEnv; - -layout (location = 0) in vec3 inUVW; - -layout (location = 0) out vec4 outColor; - -layout (binding = 1) uniform UBOParams { - vec4 lights[4]; - float exposure; - float gamma; -} uboParams; - -// From http://filmicworlds.com/blog/filmic-tonemapping-operators/ -vec3 Uncharted2Tonemap(vec3 color) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - float W = 11.2; - return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; -} - -void main() -{ - vec3 color = texture(samplerEnv, inUVW).rgb; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap(vec3(11.2f))); - // Gamma correction - color = pow(color, vec3(1.0f / uboParams.gamma)); - - outColor = vec4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pbribl/skybox.frag.spv b/shaders/glsl/pbribl/skybox.frag.spv deleted file mode 100644 index ac4c939c..00000000 Binary files a/shaders/glsl/pbribl/skybox.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbribl/skybox.vert b/shaders/glsl/pbribl/skybox.vert deleted file mode 100644 index b93a3c35..00000000 --- a/shaders/glsl/pbribl/skybox.vert +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outUVW; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUVW = inPos; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/pbribl/skybox.vert.spv b/shaders/glsl/pbribl/skybox.vert.spv deleted file mode 100644 index fcbc5bc4..00000000 Binary files a/shaders/glsl/pbribl/skybox.vert.spv and /dev/null differ diff --git a/shaders/glsl/pbrtexture/filtercube.vert b/shaders/glsl/pbrtexture/filtercube.vert deleted file mode 100644 index 1226e28e..00000000 --- a/shaders/glsl/pbrtexture/filtercube.vert +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout(push_constant) uniform PushConsts { - layout (offset = 0) mat4 mvp; -} pushConsts; - -layout (location = 0) out vec3 outUVW; - -out gl_PerVertex { - vec4 gl_Position; -}; - -void main() -{ - outUVW = inPos; - gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/pbrtexture/filtercube.vert.spv b/shaders/glsl/pbrtexture/filtercube.vert.spv deleted file mode 100644 index 220a3df4..00000000 Binary files a/shaders/glsl/pbrtexture/filtercube.vert.spv and /dev/null differ diff --git a/shaders/glsl/pbrtexture/genbrdflut.frag b/shaders/glsl/pbrtexture/genbrdflut.frag deleted file mode 100644 index d3aba88b..00000000 --- a/shaders/glsl/pbrtexture/genbrdflut.frag +++ /dev/null @@ -1,90 +0,0 @@ -#version 450 - -layout (location = 0) in vec2 inUV; -layout (location = 0) out vec4 outColor; -layout (constant_id = 0) const uint NUM_SAMPLES = 1024u; - -const float PI = 3.1415926536; - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(vec2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,vec2(a,b)); - float sn= mod(dt,3.14); - return fract(sin(sn) * c); -} - -vec2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return vec2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 tangentX = normalize(cross(up, normal)); - vec3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Geometric Shadowing function -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float k = (roughness * roughness) / 2.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -vec2 BRDF(float NoV, float roughness) -{ - // Normal always points along z-axis for the 2D lookup - const vec3 N = vec3(0.0, 0.0, 1.0); - vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV); - - vec2 LUT = vec2(0.0); - for(uint i = 0u; i < NUM_SAMPLES; i++) { - vec2 Xi = hammersley2d(i, NUM_SAMPLES); - vec3 H = importanceSample_GGX(Xi, roughness, N); - vec3 L = 2.0 * dot(V, H) * H - V; - - float dotNL = max(dot(N, L), 0.0); - float dotNV = max(dot(N, V), 0.0); - float dotVH = max(dot(V, H), 0.0); - float dotNH = max(dot(H, N), 0.0); - - if (dotNL > 0.0) { - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - float G_Vis = (G * dotVH) / (dotNH * dotNV); - float Fc = pow(1.0 - dotVH, 5.0); - LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis); - } - } - return LUT / float(NUM_SAMPLES); -} - -void main() -{ - outColor = vec4(BRDF(inUV.s, inUV.t), 0.0, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pbrtexture/genbrdflut.frag.spv b/shaders/glsl/pbrtexture/genbrdflut.frag.spv deleted file mode 100644 index f83c5e38..00000000 Binary files a/shaders/glsl/pbrtexture/genbrdflut.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbrtexture/genbrdflut.vert b/shaders/glsl/pbrtexture/genbrdflut.vert deleted file mode 100644 index f3dd2335..00000000 --- a/shaders/glsl/pbrtexture/genbrdflut.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} \ No newline at end of file diff --git a/shaders/glsl/pbrtexture/genbrdflut.vert.spv b/shaders/glsl/pbrtexture/genbrdflut.vert.spv deleted file mode 100644 index fc2b37dd..00000000 Binary files a/shaders/glsl/pbrtexture/genbrdflut.vert.spv and /dev/null differ diff --git a/shaders/glsl/pbrtexture/irradiancecube.frag b/shaders/glsl/pbrtexture/irradiancecube.frag deleted file mode 100644 index 3232db48..00000000 --- a/shaders/glsl/pbrtexture/irradiancecube.frag +++ /dev/null @@ -1,37 +0,0 @@ -// Generates an irradiance cube from an environment map using convolution - -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 0) out vec4 outColor; -layout (binding = 0) uniform samplerCube samplerEnv; - -layout(push_constant) uniform PushConsts { - layout (offset = 64) float deltaPhi; - layout (offset = 68) float deltaTheta; -} consts; - -#define PI 3.1415926535897932384626433832795 - -void main() -{ - vec3 N = normalize(inPos); - vec3 up = vec3(0.0, 1.0, 0.0); - vec3 right = normalize(cross(up, N)); - up = cross(N, right); - - const float TWO_PI = PI * 2.0; - const float HALF_PI = PI * 0.5; - - vec3 color = vec3(0.0); - uint sampleCount = 0u; - for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) { - for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) { - vec3 tempVec = cos(phi) * right + sin(phi) * up; - vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec; - color += texture(samplerEnv, sampleVector).rgb * cos(theta) * sin(theta); - sampleCount++; - } - } - outColor = vec4(PI * color / float(sampleCount), 1.0); -} diff --git a/shaders/glsl/pbrtexture/irradiancecube.frag.spv b/shaders/glsl/pbrtexture/irradiancecube.frag.spv deleted file mode 100644 index a369970e..00000000 Binary files a/shaders/glsl/pbrtexture/irradiancecube.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbrtexture/pbrtexture.frag b/shaders/glsl/pbrtexture/pbrtexture.frag deleted file mode 100644 index afe04070..00000000 --- a/shaders/glsl/pbrtexture/pbrtexture.frag +++ /dev/null @@ -1,173 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inWorldPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec4 inTangent; - -layout (binding = 0) uniform UBO { - mat4 projection; - mat4 model; - mat4 view; - vec3 camPos; -} ubo; - -layout (binding = 1) uniform UBOParams { - vec4 lights[4]; - float exposure; - float gamma; -} uboParams; - -layout (binding = 2) uniform samplerCube samplerIrradiance; -layout (binding = 3) uniform sampler2D samplerBRDFLUT; -layout (binding = 4) uniform samplerCube prefilteredMap; - -layout (binding = 5) uniform sampler2D albedoMap; -layout (binding = 6) uniform sampler2D normalMap; -layout (binding = 7) uniform sampler2D aoMap; -layout (binding = 8) uniform sampler2D metallicMap; -layout (binding = 9) uniform sampler2D roughnessMap; - - -layout (location = 0) out vec4 outColor; - -#define PI 3.1415926535897932384626433832795 -#define ALBEDO pow(texture(albedoMap, inUV).rgb, vec3(2.2)) - -// From http://filmicgames.com/archives/75 -vec3 Uncharted2Tonemap(vec3 x) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F; -} - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -vec3 F_Schlick(float cosTheta, vec3 F0) -{ - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} -vec3 F_SchlickR(float cosTheta, vec3 F0, float roughness) -{ - return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); -} - -vec3 prefilteredReflection(vec3 R, float roughness) -{ - const float MAX_REFLECTION_LOD = 9.0; // todo: param/const - float lod = roughness * MAX_REFLECTION_LOD; - float lodf = floor(lod); - float lodc = ceil(lod); - vec3 a = textureLod(prefilteredMap, R, lodf).rgb; - vec3 b = textureLod(prefilteredMap, R, lodc).rgb; - return mix(a, b, lod - lodf); -} - -vec3 specularContribution(vec3 L, vec3 V, vec3 N, vec3 F0, float metallic, float roughness) -{ - // Precalculate vectors and dot products - vec3 H = normalize (V + L); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - - // Light color fixed - vec3 lightColor = vec3(1.0); - - vec3 color = vec3(0.0); - - if (dotNL > 0.0) { - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, roughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - vec3 F = F_Schlick(dotNV, F0); - vec3 spec = D * F * G / (4.0 * dotNL * dotNV + 0.001); - vec3 kD = (vec3(1.0) - F) * (1.0 - metallic); - color += (kD * ALBEDO / PI + spec) * dotNL; - } - - return color; -} - -vec3 calculateNormal() -{ - vec3 tangentNormal = texture(normalMap, inUV).xyz * 2.0 - 1.0; - - vec3 N = normalize(inNormal); - vec3 T = normalize(inTangent.xyz); - vec3 B = normalize(cross(N, T)); - mat3 TBN = mat3(T, B, N); - return normalize(TBN * tangentNormal); -} - -void main() -{ - vec3 N = calculateNormal(); - - vec3 V = normalize(ubo.camPos - inWorldPos); - vec3 R = reflect(-V, N); - - float metallic = texture(metallicMap, inUV).r; - float roughness = texture(roughnessMap, inUV).r; - - vec3 F0 = vec3(0.04); - F0 = mix(F0, ALBEDO, metallic); - - vec3 Lo = vec3(0.0); - for(int i = 0; i < uboParams.lights[i].length(); i++) { - vec3 L = normalize(uboParams.lights[i].xyz - inWorldPos); - Lo += specularContribution(L, V, N, F0, metallic, roughness); - } - - vec2 brdf = texture(samplerBRDFLUT, vec2(max(dot(N, V), 0.0), roughness)).rg; - vec3 reflection = prefilteredReflection(R, roughness).rgb; - vec3 irradiance = texture(samplerIrradiance, N).rgb; - - // Diffuse based on irradiance - vec3 diffuse = irradiance * ALBEDO; - - vec3 F = F_SchlickR(max(dot(N, V), 0.0), F0, roughness); - - // Specular reflectance - vec3 specular = reflection * (F * brdf.x + brdf.y); - - // Ambient part - vec3 kD = 1.0 - F; - kD *= 1.0 - metallic; - vec3 ambient = (kD * diffuse + specular) * texture(aoMap, inUV).rrr; - - vec3 color = ambient + Lo; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap(vec3(11.2f))); - // Gamma correction - color = pow(color, vec3(1.0f / uboParams.gamma)); - - outColor = vec4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pbrtexture/pbrtexture.frag.spv b/shaders/glsl/pbrtexture/pbrtexture.frag.spv deleted file mode 100644 index 9891cd33..00000000 Binary files a/shaders/glsl/pbrtexture/pbrtexture.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbrtexture/pbrtexture.vert b/shaders/glsl/pbrtexture/pbrtexture.vert deleted file mode 100644 index ee6b064a..00000000 --- a/shaders/glsl/pbrtexture/pbrtexture.vert +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec4 inTangent; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - //mat4 normal; - vec3 camPos; -} ubo; - -layout (location = 0) out vec3 outWorldPos; -layout (location = 1) out vec3 outNormal; -layout (location = 2) out vec2 outUV; -layout (location = 3) out vec4 outTangent; - -void main() -{ - vec3 locPos = vec3(ubo.model * vec4(inPos, 1.0)); - outWorldPos = locPos; - outNormal = mat3(ubo.model) * inNormal; - outTangent = vec4(mat3(ubo.model) * inTangent.xyz, inTangent.w); - outUV = inUV; - gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0); -} diff --git a/shaders/glsl/pbrtexture/pbrtexture.vert.spv b/shaders/glsl/pbrtexture/pbrtexture.vert.spv deleted file mode 100644 index 0a28f71e..00000000 Binary files a/shaders/glsl/pbrtexture/pbrtexture.vert.spv and /dev/null differ diff --git a/shaders/glsl/pbrtexture/prefilterenvmap.frag b/shaders/glsl/pbrtexture/prefilterenvmap.frag deleted file mode 100644 index ae1212ed..00000000 --- a/shaders/glsl/pbrtexture/prefilterenvmap.frag +++ /dev/null @@ -1,105 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 0) out vec4 outColor; - -layout (binding = 0) uniform samplerCube samplerEnv; - -layout(push_constant) uniform PushConsts { - layout (offset = 64) float roughness; - layout (offset = 68) uint numSamples; -} consts; - -const float PI = 3.1415926536; - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(vec2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,vec2(a,b)); - float sn= mod(dt,3.14); - return fract(sin(sn) * c); -} - -vec2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return vec2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 tangentX = normalize(cross(up, normal)); - vec3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Normal Distribution function -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -vec3 prefilterEnvMap(vec3 R, float roughness) -{ - vec3 N = R; - vec3 V = R; - vec3 color = vec3(0.0); - float totalWeight = 0.0; - float envMapDim = float(textureSize(samplerEnv, 0).s); - for(uint i = 0u; i < consts.numSamples; i++) { - vec2 Xi = hammersley2d(i, consts.numSamples); - vec3 H = importanceSample_GGX(Xi, roughness, N); - vec3 L = 2.0 * dot(V, H) * H - V; - float dotNL = clamp(dot(N, L), 0.0, 1.0); - if(dotNL > 0.0) { - // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ - - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotVH = clamp(dot(V, H), 0.0, 1.0); - - // Probability Distribution Function - float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; - // Slid angle of current smple - float omegaS = 1.0 / (float(consts.numSamples) * pdf); - // Solid angle of 1 pixel across all cube faces - float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); - // Biased (+1.0) mip level for better result - float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); - color += textureLod(samplerEnv, L, mipLevel).rgb * dotNL; - totalWeight += dotNL; - - } - } - return (color / totalWeight); -} - - -void main() -{ - vec3 N = normalize(inPos); - outColor = vec4(prefilterEnvMap(N, consts.roughness), 1.0); -} diff --git a/shaders/glsl/pbrtexture/prefilterenvmap.frag.spv b/shaders/glsl/pbrtexture/prefilterenvmap.frag.spv deleted file mode 100644 index aa5955dc..00000000 Binary files a/shaders/glsl/pbrtexture/prefilterenvmap.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbrtexture/skybox.frag b/shaders/glsl/pbrtexture/skybox.frag deleted file mode 100644 index e46fdfe0..00000000 --- a/shaders/glsl/pbrtexture/skybox.frag +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (binding = 2) uniform samplerCube samplerEnv; - -layout (location = 0) in vec3 inUVW; - -layout (location = 0) out vec4 outColor; - -layout (binding = 1) uniform UBOParams { - vec4 lights[4]; - float exposure; - float gamma; -} uboParams; - -// From http://filmicworlds.com/blog/filmic-tonemapping-operators/ -vec3 Uncharted2Tonemap(vec3 color) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - float W = 11.2; - return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; -} - -void main() -{ - vec3 color = texture(samplerEnv, inUVW).rgb; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap(vec3(11.2f))); - // Gamma correction - color = pow(color, vec3(1.0f / uboParams.gamma)); - - outColor = vec4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pbrtexture/skybox.frag.spv b/shaders/glsl/pbrtexture/skybox.frag.spv deleted file mode 100644 index ac4c939c..00000000 Binary files a/shaders/glsl/pbrtexture/skybox.frag.spv and /dev/null differ diff --git a/shaders/glsl/pbrtexture/skybox.vert b/shaders/glsl/pbrtexture/skybox.vert deleted file mode 100644 index b93a3c35..00000000 --- a/shaders/glsl/pbrtexture/skybox.vert +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outUVW; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUVW = inPos; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/pbrtexture/skybox.vert.spv b/shaders/glsl/pbrtexture/skybox.vert.spv deleted file mode 100644 index fcbc5bc4..00000000 Binary files a/shaders/glsl/pbrtexture/skybox.vert.spv and /dev/null differ diff --git a/shaders/glsl/pipelines/phong.frag b/shaders/glsl/pipelines/phong.frag deleted file mode 100644 index b207e798..00000000 --- a/shaders/glsl/pipelines/phong.frag +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - // Desaturate color - vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65)); - - // High ambient colors because mesh materials are pretty dark - vec3 ambient = color * vec3(1.0); - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * color; - vec3 specular = pow(max(dot(R, V), 0.0), 32.0) * vec3(0.35); - outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pipelines/phong.frag.spv b/shaders/glsl/pipelines/phong.frag.spv deleted file mode 100644 index d9fbe6c4..00000000 Binary files a/shaders/glsl/pipelines/phong.frag.spv and /dev/null differ diff --git a/shaders/glsl/pipelines/phong.vert b/shaders/glsl/pipelines/phong.vert deleted file mode 100644 index c0069072..00000000 --- a/shaders/glsl/pipelines/phong.vert +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(ubo.model) * inNormal; - vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/pipelines/phong.vert.spv b/shaders/glsl/pipelines/phong.vert.spv deleted file mode 100644 index b22327fb..00000000 Binary files a/shaders/glsl/pipelines/phong.vert.spv and /dev/null differ diff --git a/shaders/glsl/pipelines/toon.frag b/shaders/glsl/pipelines/toon.frag deleted file mode 100644 index b947da36..00000000 --- a/shaders/glsl/pipelines/toon.frag +++ /dev/null @@ -1,35 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - // Desaturate color - vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65)); - - // High ambient colors because mesh materials are pretty dark - vec3 ambient = color * vec3(1.0); - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * color; - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); - outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0); - - float intensity = dot(N,L); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - outFragColor.rgb = inColor * 3.0 * shade; -} \ No newline at end of file diff --git a/shaders/glsl/pipelines/toon.frag.spv b/shaders/glsl/pipelines/toon.frag.spv deleted file mode 100644 index e5b75b39..00000000 Binary files a/shaders/glsl/pipelines/toon.frag.spv and /dev/null differ diff --git a/shaders/glsl/pipelines/toon.vert b/shaders/glsl/pipelines/toon.vert deleted file mode 100644 index c0069072..00000000 --- a/shaders/glsl/pipelines/toon.vert +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(ubo.model) * inNormal; - vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/pipelines/toon.vert.spv b/shaders/glsl/pipelines/toon.vert.spv deleted file mode 100644 index b22327fb..00000000 Binary files a/shaders/glsl/pipelines/toon.vert.spv and /dev/null differ diff --git a/shaders/glsl/pipelines/wireframe.frag b/shaders/glsl/pipelines/wireframe.frag deleted file mode 100644 index 1ba23576..00000000 --- a/shaders/glsl/pipelines/wireframe.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor.rgb = inColor * 1.5; -} \ No newline at end of file diff --git a/shaders/glsl/pipelines/wireframe.frag.spv b/shaders/glsl/pipelines/wireframe.frag.spv deleted file mode 100644 index 1f294e24..00000000 Binary files a/shaders/glsl/pipelines/wireframe.frag.spv and /dev/null differ diff --git a/shaders/glsl/pipelines/wireframe.vert b/shaders/glsl/pipelines/wireframe.vert deleted file mode 100644 index b70f4c5e..00000000 --- a/shaders/glsl/pipelines/wireframe.vert +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outColor; - -void main() -{ - outColor = inColor; - gl_Position = ubo.projection * ubo.model * inPos; -} diff --git a/shaders/glsl/pipelines/wireframe.vert.spv b/shaders/glsl/pipelines/wireframe.vert.spv deleted file mode 100644 index 58fa481c..00000000 Binary files a/shaders/glsl/pipelines/wireframe.vert.spv and /dev/null differ diff --git a/shaders/glsl/pipelinestatistics/scene.frag b/shaders/glsl/pipelinestatistics/scene.frag deleted file mode 100644 index 43f18f5f..00000000 --- a/shaders/glsl/pipelinestatistics/scene.frag +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * inColor; - vec3 specular = pow(max(dot(R, V), 0.0), 8.0) * vec3(0.75); - outFragColor = vec4(diffuse + specular, 0.5); -} \ No newline at end of file diff --git a/shaders/glsl/pipelinestatistics/scene.frag.spv b/shaders/glsl/pipelinestatistics/scene.frag.spv deleted file mode 100644 index bf0c7a10..00000000 Binary files a/shaders/glsl/pipelinestatistics/scene.frag.spv and /dev/null differ diff --git a/shaders/glsl/pipelinestatistics/scene.tesc b/shaders/glsl/pipelinestatistics/scene.tesc deleted file mode 100644 index 60693281..00000000 --- a/shaders/glsl/pipelinestatistics/scene.tesc +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (vertices = 3) out; - -layout (location = 0) in vec3 inNormal[]; -layout (location = 1) in vec3 inColor[]; -layout (location = 2) in vec3 inViewVec[]; -layout (location = 3) in vec3 inLightVec[]; - -layout (location = 0) out vec3 outNormal[3]; -layout (location = 1) out vec3 outColor[3]; -layout (location = 2) out vec3 outViewVec[3]; -layout (location = 3) out vec3 outLightVec[3]; - -void main(void) -{ - if (gl_InvocationID == 0) - { - gl_TessLevelInner[0] = 2.0; - gl_TessLevelOuter[0] = 1.0; - gl_TessLevelOuter[1] = 1.0; - gl_TessLevelOuter[2] = 1.0; - } - - gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; - outNormal[gl_InvocationID] = inNormal[gl_InvocationID]; - outColor[gl_InvocationID] = inColor[gl_InvocationID]; - outViewVec[gl_InvocationID] = inViewVec[gl_InvocationID]; - outLightVec[gl_InvocationID] = inLightVec[gl_InvocationID]; -} \ No newline at end of file diff --git a/shaders/glsl/pipelinestatistics/scene.tesc.spv b/shaders/glsl/pipelinestatistics/scene.tesc.spv deleted file mode 100644 index 6c58fd74..00000000 Binary files a/shaders/glsl/pipelinestatistics/scene.tesc.spv and /dev/null differ diff --git a/shaders/glsl/pipelinestatistics/scene.tese b/shaders/glsl/pipelinestatistics/scene.tese deleted file mode 100644 index 39f020d2..00000000 --- a/shaders/glsl/pipelinestatistics/scene.tese +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -layout (triangles) in; - -layout (location = 0) in vec3 inNormal[]; -layout (location = 1) in vec3 inColor[]; -layout (location = 2) in vec3 inViewVec[]; -layout (location = 3) in vec3 inLightVec[]; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -void main(void) -{ - gl_Position = (gl_TessCoord.x * gl_in[2].gl_Position) + - (gl_TessCoord.y * gl_in[1].gl_Position) + - (gl_TessCoord.z * gl_in[0].gl_Position); - outNormal = gl_TessCoord.x*inNormal[2] + gl_TessCoord.y*inNormal[1] + gl_TessCoord.z*inNormal[0]; - outViewVec = gl_TessCoord.x*inViewVec[2] + gl_TessCoord.y*inViewVec[1] + gl_TessCoord.z*inViewVec[0]; - outLightVec = gl_TessCoord.x*inLightVec[2] + gl_TessCoord.y*inLightVec[1] + gl_TessCoord.z*inLightVec[0]; - outColor = inColor[0]; -} \ No newline at end of file diff --git a/shaders/glsl/pipelinestatistics/scene.tese.spv b/shaders/glsl/pipelinestatistics/scene.tese.spv deleted file mode 100644 index 5cb3391a..00000000 Binary files a/shaders/glsl/pipelinestatistics/scene.tese.spv and /dev/null differ diff --git a/shaders/glsl/pipelinestatistics/scene.vert b/shaders/glsl/pipelinestatistics/scene.vert deleted file mode 100644 index fc54284e..00000000 --- a/shaders/glsl/pipelinestatistics/scene.vert +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -layout(push_constant) uniform PushConsts { - vec3 objPos; -} pushConsts; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - - vec3 locPos = vec3(ubo.modelview * vec4(inPos, 1.0)); - vec3 worldPos = vec3(ubo.modelview * vec4(inPos + pushConsts.objPos, 1.0)); - gl_Position = ubo.projection /* ubo.modelview */ * vec4(worldPos, 1.0); - - vec4 pos = ubo.modelview * vec4(worldPos, 1.0); - outNormal = mat3(ubo.modelview) * inNormal; - outLightVec = ubo.lightPos.xyz - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/pipelinestatistics/scene.vert.spv b/shaders/glsl/pipelinestatistics/scene.vert.spv deleted file mode 100644 index 0e282926..00000000 Binary files a/shaders/glsl/pipelinestatistics/scene.vert.spv and /dev/null differ diff --git a/shaders/glsl/pushconstants/pushconstants.frag b/shaders/glsl/pushconstants/pushconstants.frag deleted file mode 100644 index e1646b68..00000000 --- a/shaders/glsl/pushconstants/pushconstants.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor.rgb = inColor; -} \ No newline at end of file diff --git a/shaders/glsl/pushconstants/pushconstants.frag.spv b/shaders/glsl/pushconstants/pushconstants.frag.spv deleted file mode 100644 index 70fab31d..00000000 Binary files a/shaders/glsl/pushconstants/pushconstants.frag.spv and /dev/null differ diff --git a/shaders/glsl/pushconstants/pushconstants.vert b/shaders/glsl/pushconstants/pushconstants.vert deleted file mode 100644 index 2e2d52d8..00000000 --- a/shaders/glsl/pushconstants/pushconstants.vert +++ /dev/null @@ -1,29 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -#define lightCount 6 - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; -} ubo; - -layout(push_constant) uniform PushConsts { - vec4 color; - vec4 position; -} pushConsts; - -layout (location = 0) out vec3 outColor; - -void main() -{ - outColor = inColor * pushConsts.color.rgb; - vec3 locPos = vec3(ubo.model * vec4(inPos, 1.0)); - vec3 worldPos = locPos + pushConsts.position.xyz; - gl_Position = ubo.projection * ubo.view * vec4(worldPos, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pushconstants/pushconstants.vert.spv b/shaders/glsl/pushconstants/pushconstants.vert.spv deleted file mode 100644 index 8e305576..00000000 Binary files a/shaders/glsl/pushconstants/pushconstants.vert.spv and /dev/null differ diff --git a/shaders/glsl/pushdescriptors/cube.frag b/shaders/glsl/pushdescriptors/cube.frag deleted file mode 100644 index 21a9a458..00000000 --- a/shaders/glsl/pushdescriptors/cube.frag +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (set = 0, binding = 2) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerColorMap, inUV) * vec4(inColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pushdescriptors/cube.frag.spv b/shaders/glsl/pushdescriptors/cube.frag.spv deleted file mode 100644 index c98e777a..00000000 Binary files a/shaders/glsl/pushdescriptors/cube.frag.spv and /dev/null differ diff --git a/shaders/glsl/pushdescriptors/cube.vert b/shaders/glsl/pushdescriptors/cube.vert deleted file mode 100644 index 07d13502..00000000 --- a/shaders/glsl/pushdescriptors/cube.vert +++ /dev/null @@ -1,31 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -layout (set = 0, binding = 0) uniform UBOScene { - mat4 projection; - mat4 view; -} uboCamera; - -layout (set = 0, binding = 1) uniform UBOModel { - mat4 local; -} uboModel; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec2 outUV; - -out gl_PerVertex { - vec4 gl_Position; -}; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - outUV = inUV; - gl_Position = uboCamera.projection * uboCamera.view * uboModel.local * vec4(inPos.xyz, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/pushdescriptors/cube.vert.spv b/shaders/glsl/pushdescriptors/cube.vert.spv deleted file mode 100644 index 9b5b8b2c..00000000 Binary files a/shaders/glsl/pushdescriptors/cube.vert.spv and /dev/null differ diff --git a/shaders/glsl/radialblur/colorpass.frag b/shaders/glsl/radialblur/colorpass.frag deleted file mode 100644 index 440722c6..00000000 --- a/shaders/glsl/radialblur/colorpass.frag +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerGradientRamp; - -layout (location = 0) in vec3 inColor; -layout (location = 1) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - // Use max. color channel value to detect bright glow emitters - if ((inColor.r >= 0.9) || (inColor.g >= 0.9) || (inColor.b >= 0.9)) - { - outFragColor.rgb = texture(samplerGradientRamp, inUV).rgb; - } - else - { - outFragColor.rgb = inColor; - } -} \ No newline at end of file diff --git a/shaders/glsl/radialblur/colorpass.frag.spv b/shaders/glsl/radialblur/colorpass.frag.spv deleted file mode 100644 index 07a97ca3..00000000 Binary files a/shaders/glsl/radialblur/colorpass.frag.spv and /dev/null differ diff --git a/shaders/glsl/radialblur/colorpass.vert b/shaders/glsl/radialblur/colorpass.vert deleted file mode 100644 index 69a126fd..00000000 --- a/shaders/glsl/radialblur/colorpass.vert +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - float gradientPos; -} ubo; - -layout (location = 0) out vec3 outColor; -layout (location = 1) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outColor = inColor; - outUV = vec2(ubo.gradientPos, 0.0f); - gl_Position = ubo.projection * ubo.model * vec4(inPos, 1.0); -} diff --git a/shaders/glsl/radialblur/colorpass.vert.spv b/shaders/glsl/radialblur/colorpass.vert.spv deleted file mode 100644 index 5635051a..00000000 Binary files a/shaders/glsl/radialblur/colorpass.vert.spv and /dev/null differ diff --git a/shaders/glsl/radialblur/phongpass.frag b/shaders/glsl/radialblur/phongpass.frag deleted file mode 100644 index 719a6272..00000000 --- a/shaders/glsl/radialblur/phongpass.frag +++ /dev/null @@ -1,33 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerGradientRamp; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inEyePos; -layout (location = 3) in vec3 inLightVec; -layout (location = 4) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - // No light calculations for glow color - // Use max. color channel value - // to detect bright glow emitters - if ((inColor.r >= 0.9) || (inColor.g >= 0.9) || (inColor.b >= 0.9)) - { - outFragColor.rgb = texture(samplerGradientRamp, inUV).rgb; - } - else - { - vec3 Eye = normalize(-inEyePos); - vec3 Reflected = normalize(reflect(-inLightVec, inNormal)); - - vec4 IAmbient = vec4(0.2, 0.2, 0.2, 1.0); - vec4 IDiffuse = vec4(0.5, 0.5, 0.5, 0.5) * max(dot(inNormal, inLightVec), 0.0); - float specular = 0.25; - vec4 ISpecular = vec4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 4.0) * specular; - outFragColor = vec4((IAmbient + IDiffuse) * vec4(inColor, 1.0) + ISpecular); - } -} \ No newline at end of file diff --git a/shaders/glsl/radialblur/phongpass.frag.spv b/shaders/glsl/radialblur/phongpass.frag.spv deleted file mode 100644 index 33b35eb9..00000000 Binary files a/shaders/glsl/radialblur/phongpass.frag.spv and /dev/null differ diff --git a/shaders/glsl/radialblur/phongpass.vert b/shaders/glsl/radialblur/phongpass.vert deleted file mode 100644 index 65233fc4..00000000 --- a/shaders/glsl/radialblur/phongpass.vert +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 pos; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - float gradientPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outEyePos; -layout (location = 3) out vec3 outLightVec; -layout (location = 4) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - outUV = vec2(ubo.gradientPos, 0.0); - gl_Position = ubo.projection * ubo.model * pos; - outEyePos = vec3(ubo.model * pos); - vec4 lightPos = vec4(0.0, 0.0, -5.0, 1.0);// * ubo.model; - outLightVec = normalize(lightPos.xyz - pos.xyz); -} diff --git a/shaders/glsl/radialblur/phongpass.vert.spv b/shaders/glsl/radialblur/phongpass.vert.spv deleted file mode 100644 index f265539d..00000000 Binary files a/shaders/glsl/radialblur/phongpass.vert.spv and /dev/null differ diff --git a/shaders/glsl/radialblur/radialblur.frag b/shaders/glsl/radialblur/radialblur.frag deleted file mode 100644 index 59e7b666..00000000 --- a/shaders/glsl/radialblur/radialblur.frag +++ /dev/null @@ -1,35 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (binding = 0) uniform UBO -{ - float radialBlurScale; - float radialBlurStrength; - vec2 radialOrigin; -} ubo; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - ivec2 texDim = textureSize(samplerColor, 0); - vec2 radialSize = vec2(1.0 / texDim.s, 1.0 / texDim.t); - - vec2 UV = inUV; - - vec4 color = vec4(0.0, 0.0, 0.0, 0.0); - UV += radialSize * 0.5 - ubo.radialOrigin; - - #define samples 32 - - for (int i = 0; i < samples; i++) - { - float scale = 1.0 - ubo.radialBlurScale * (float(i) / float(samples-1)); - color += texture(samplerColor, UV * scale + ubo.radialOrigin); - } - - outFragColor = (color / samples) * ubo.radialBlurStrength; -} \ No newline at end of file diff --git a/shaders/glsl/radialblur/radialblur.frag.spv b/shaders/glsl/radialblur/radialblur.frag.spv deleted file mode 100644 index 521a3334..00000000 Binary files a/shaders/glsl/radialblur/radialblur.frag.spv and /dev/null differ diff --git a/shaders/glsl/radialblur/radialblur.vert b/shaders/glsl/radialblur/radialblur.vert deleted file mode 100644 index a5d60d0e..00000000 --- a/shaders/glsl/radialblur/radialblur.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/radialblur/radialblur.vert.spv b/shaders/glsl/radialblur/radialblur.vert.spv deleted file mode 100644 index 4040f608..00000000 Binary files a/shaders/glsl/radialblur/radialblur.vert.spv and /dev/null differ diff --git a/shaders/glsl/rayquery/scene.frag b/shaders/glsl/rayquery/scene.frag deleted file mode 100644 index 4f40a1a1..00000000 --- a/shaders/glsl/rayquery/scene.frag +++ /dev/null @@ -1,37 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : enable -#extension GL_EXT_ray_query : enable - -layout (binding = 1, set = 0) uniform accelerationStructureEXT topLevelAS; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; -layout (location = 4) in vec3 inWorldPos; - -layout (location = 0) out vec4 outFragColor; - -#define ambient 0.1 - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = normalize(-reflect(L, N)); - vec3 diffuse = max(dot(N, L), ambient) * inColor; - - outFragColor = vec4(diffuse, 1.0); - - rayQueryEXT rayQuery; - rayQueryInitializeEXT(rayQuery, topLevelAS, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, inWorldPos, 0.01, L, 1000.0); - - // Traverse the acceleration structure and store information about the first intersection (if any) - rayQueryProceedEXT(rayQuery); - - // If the intersection has hit a triangle, the fragment is shadowed - if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionTriangleEXT ) { - outFragColor *= 0.1; - } -} diff --git a/shaders/glsl/rayquery/scene.frag.spv b/shaders/glsl/rayquery/scene.frag.spv deleted file mode 100644 index 2465e577..00000000 Binary files a/shaders/glsl/rayquery/scene.frag.spv and /dev/null differ diff --git a/shaders/glsl/rayquery/scene.vert b/shaders/glsl/rayquery/scene.vert deleted file mode 100644 index 09567412..00000000 --- a/shaders/glsl/rayquery/scene.vert +++ /dev/null @@ -1,33 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - vec3 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; -layout (location = 4) out vec3 outWorldPos; - -void main() -{ - outColor = inColor; - outNormal = inNormal; - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); - vec4 pos = ubo.model * vec4(inPos, 1.0); - outWorldPos = vec3(ubo.model * vec4(inPos, 1.0)); - outNormal = mat3(ubo.model) * inNormal; - outLightVec = normalize(ubo.lightPos - inPos); - outViewVec = -pos.xyz; -} - diff --git a/shaders/glsl/rayquery/scene.vert.spv b/shaders/glsl/rayquery/scene.vert.spv deleted file mode 100644 index 7d9008a8..00000000 Binary files a/shaders/glsl/rayquery/scene.vert.spv and /dev/null differ diff --git a/shaders/glsl/raytracingbasic/closesthit.rchit b/shaders/glsl/raytracingbasic/closesthit.rchit deleted file mode 100644 index 44936f20..00000000 --- a/shaders/glsl/raytracingbasic/closesthit.rchit +++ /dev/null @@ -1,12 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : enable -#extension GL_EXT_nonuniform_qualifier : enable - -layout(location = 0) rayPayloadInEXT vec3 hitValue; -hitAttributeEXT vec2 attribs; - -void main() -{ - const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y); - hitValue = barycentricCoords; -} diff --git a/shaders/glsl/raytracingbasic/closesthit.rchit.spv b/shaders/glsl/raytracingbasic/closesthit.rchit.spv deleted file mode 100644 index dd8cfc08..00000000 Binary files a/shaders/glsl/raytracingbasic/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/glsl/raytracingbasic/miss.rmiss b/shaders/glsl/raytracingbasic/miss.rmiss deleted file mode 100644 index 25633fbe..00000000 --- a/shaders/glsl/raytracingbasic/miss.rmiss +++ /dev/null @@ -1,9 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : enable - -layout(location = 0) rayPayloadInEXT vec3 hitValue; - -void main() -{ - hitValue = vec3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingbasic/miss.rmiss.spv b/shaders/glsl/raytracingbasic/miss.rmiss.spv deleted file mode 100644 index 58fb3309..00000000 Binary files a/shaders/glsl/raytracingbasic/miss.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracingbasic/raygen.rgen b/shaders/glsl/raytracingbasic/raygen.rgen deleted file mode 100644 index 7f803f35..00000000 --- a/shaders/glsl/raytracingbasic/raygen.rgen +++ /dev/null @@ -1,32 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : enable - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 1, set = 0, rgba8) uniform image2D image; -layout(binding = 2, set = 0) uniform CameraProperties -{ - mat4 viewInverse; - mat4 projInverse; -} cam; - -layout(location = 0) rayPayloadEXT vec3 hitValue; - -void main() -{ - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; - - vec4 origin = cam.viewInverse * vec4(0,0,0,1); - vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ; - vec4 direction = cam.viewInverse*vec4(normalize(target.xyz), 0) ; - - float tmin = 0.001; - float tmax = 10000.0; - - hitValue = vec3(0.0); - - traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0); - - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue, 0.0)); -} diff --git a/shaders/glsl/raytracingbasic/raygen.rgen.spv b/shaders/glsl/raytracingbasic/raygen.rgen.spv deleted file mode 100644 index ce9413a9..00000000 Binary files a/shaders/glsl/raytracingbasic/raygen.rgen.spv and /dev/null differ diff --git a/shaders/glsl/raytracingcallable/callable1.rcall b/shaders/glsl/raytracingcallable/callable1.rcall deleted file mode 100644 index fc50a5ea..00000000 --- a/shaders/glsl/raytracingcallable/callable1.rcall +++ /dev/null @@ -1,11 +0,0 @@ -#version 460 core -#extension GL_EXT_ray_tracing : enable - -layout(location = 0) callableDataInEXT vec3 outColor; - -void main() -{ - // Generate a checker board pattern - vec2 pos = vec2(gl_LaunchIDEXT / 8); - outColor = vec3(mod(pos.x + mod(pos.y, 2.0), 2.0)); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingcallable/callable1.rcall.spv b/shaders/glsl/raytracingcallable/callable1.rcall.spv deleted file mode 100644 index f022a111..00000000 Binary files a/shaders/glsl/raytracingcallable/callable1.rcall.spv and /dev/null differ diff --git a/shaders/glsl/raytracingcallable/callable2.rcall b/shaders/glsl/raytracingcallable/callable2.rcall deleted file mode 100644 index 525aab0f..00000000 --- a/shaders/glsl/raytracingcallable/callable2.rcall +++ /dev/null @@ -1,9 +0,0 @@ -#version 460 core -#extension GL_EXT_ray_tracing : enable - -layout(location = 0) callableDataInEXT vec3 outColor; - -void main() -{ - outColor = vec3(0.0, 1.0, 0.0); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingcallable/callable2.rcall.spv b/shaders/glsl/raytracingcallable/callable2.rcall.spv deleted file mode 100644 index da3165a8..00000000 Binary files a/shaders/glsl/raytracingcallable/callable2.rcall.spv and /dev/null differ diff --git a/shaders/glsl/raytracingcallable/callable3.rcall b/shaders/glsl/raytracingcallable/callable3.rcall deleted file mode 100644 index 1cc3a701..00000000 --- a/shaders/glsl/raytracingcallable/callable3.rcall +++ /dev/null @@ -1,11 +0,0 @@ -#version 460 core -#extension GL_EXT_ray_tracing : enable - -layout(location = 0) callableDataInEXT vec3 outColor; - -void main() -{ - // Generate a line pattern - vec2 pos = vec2(gl_LaunchIDEXT / 8); - outColor = vec3(mod(pos.y, 2.0)); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingcallable/callable3.rcall.spv b/shaders/glsl/raytracingcallable/callable3.rcall.spv deleted file mode 100644 index 8c3a0933..00000000 Binary files a/shaders/glsl/raytracingcallable/callable3.rcall.spv and /dev/null differ diff --git a/shaders/glsl/raytracingcallable/closesthit.rchit b/shaders/glsl/raytracingcallable/closesthit.rchit deleted file mode 100644 index 210a2d59..00000000 --- a/shaders/glsl/raytracingcallable/closesthit.rchit +++ /dev/null @@ -1,17 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require -#extension GL_EXT_nonuniform_qualifier : enable - -layout(location = 0) rayPayloadInEXT vec3 hitValue; -layout(location = 0) callableDataEXT vec3 outColor; - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; - -void main() -{ - // Execute the callable shader indexed by the current geometry being hit - // For our sample this means that the first callable shader in the SBT is invoked for the first triangle, the second callable shader for the second triangle, etc. - executeCallableEXT(gl_GeometryIndexEXT, 0); - - hitValue = outColor; -} diff --git a/shaders/glsl/raytracingcallable/closesthit.rchit.spv b/shaders/glsl/raytracingcallable/closesthit.rchit.spv deleted file mode 100644 index c56de05a..00000000 Binary files a/shaders/glsl/raytracingcallable/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/glsl/raytracingcallable/miss.rmiss b/shaders/glsl/raytracingcallable/miss.rmiss deleted file mode 100644 index 577f7e8e..00000000 --- a/shaders/glsl/raytracingcallable/miss.rmiss +++ /dev/null @@ -1,9 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require - -layout(location = 0) rayPayloadInEXT vec3 hitValue; - -void main() -{ - hitValue = vec3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingcallable/miss.rmiss.spv b/shaders/glsl/raytracingcallable/miss.rmiss.spv deleted file mode 100644 index 58fb3309..00000000 Binary files a/shaders/glsl/raytracingcallable/miss.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracingcallable/raygen.rgen b/shaders/glsl/raytracingcallable/raygen.rgen deleted file mode 100644 index c8552e8f..00000000 --- a/shaders/glsl/raytracingcallable/raygen.rgen +++ /dev/null @@ -1,32 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 1, set = 0, rgba8) uniform image2D image; -layout(binding = 2, set = 0) uniform CameraProperties -{ - mat4 viewInverse; - mat4 projInverse; -} cam; - -layout(location = 0) rayPayloadEXT vec3 hitValue; - -void main() -{ - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; - - vec4 origin = cam.viewInverse * vec4(0,0,0,1); - vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ; - vec4 direction = cam.viewInverse*vec4(normalize(target.xyz / target.w), 0) ; - - uint rayFlags = gl_RayFlagsOpaqueEXT; - uint cullMask = 0xff; - float tmin = 0.001; - float tmax = 10000.0; - - traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0); - - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue, 0.0)); -} diff --git a/shaders/glsl/raytracingcallable/raygen.rgen.spv b/shaders/glsl/raytracingcallable/raygen.rgen.spv deleted file mode 100644 index 0f7af95b..00000000 Binary files a/shaders/glsl/raytracingcallable/raygen.rgen.spv and /dev/null differ diff --git a/shaders/glsl/raytracinggltf/anyhit.rahit b/shaders/glsl/raytracinggltf/anyhit.rahit deleted file mode 100644 index 7ca0bea0..00000000 --- a/shaders/glsl/raytracinggltf/anyhit.rahit +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ -#version 460 - -#extension GL_EXT_ray_tracing : require -#extension GL_GOOGLE_include_directive : require -#extension GL_EXT_nonuniform_qualifier : require -#extension GL_EXT_buffer_reference2 : require -#extension GL_EXT_scalar_block_layout : require -#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require - -layout(location = 3) rayPayloadInEXT uint payloadSeed; - -hitAttributeEXT vec2 attribs; - -layout(binding = 3, set = 0) uniform sampler2D image; - -struct GeometryNode { - uint64_t vertexBufferDeviceAddress; - uint64_t indexBufferDeviceAddress; - int textureIndexBaseColor; - int textureIndexOcclusion; -}; -layout(binding = 4, set = 0) buffer GeometryNodes { GeometryNode nodes[]; } geometryNodes; - -layout(binding = 5, set = 0) uniform sampler2D textures[]; - -#include "bufferreferences.glsl" -#include "geometrytypes.glsl" -#include "random.glsl" - -void main() -{ - Triangle tri = unpackTriangle(gl_PrimitiveID, 112); - GeometryNode geometryNode = geometryNodes.nodes[gl_GeometryIndexEXT]; - vec4 color = texture(textures[nonuniformEXT(geometryNode.textureIndexBaseColor)], tri.uv); - // If the alpha value of the texture at the current UV coordinates is below a given threshold, we'll ignore this intersection - // That way ray traversal will be stopped and the miss shader will be invoked - if (color.a < 0.9) { - if(rnd(payloadSeed) > color.a) { - ignoreIntersectionEXT; - } - } -} \ No newline at end of file diff --git a/shaders/glsl/raytracinggltf/anyhit.rahit.spv b/shaders/glsl/raytracinggltf/anyhit.rahit.spv deleted file mode 100644 index 94915183..00000000 Binary files a/shaders/glsl/raytracinggltf/anyhit.rahit.spv and /dev/null differ diff --git a/shaders/glsl/raytracinggltf/bufferreferences.glsl b/shaders/glsl/raytracinggltf/bufferreferences.glsl deleted file mode 100644 index e2b0771f..00000000 --- a/shaders/glsl/raytracinggltf/bufferreferences.glsl +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -layout(push_constant) uniform BufferReferences { - uint64_t vertices; - uint64_t indices; - uint64_t bufferAddress; -} bufferReferences; - -layout(buffer_reference, scalar) buffer Vertices {vec4 v[]; }; -layout(buffer_reference, scalar) buffer Indices {uint i[]; }; -layout(buffer_reference, scalar) buffer Data {vec4 f[]; }; \ No newline at end of file diff --git a/shaders/glsl/raytracinggltf/closesthit.rchit b/shaders/glsl/raytracinggltf/closesthit.rchit deleted file mode 100644 index 981b2c8b..00000000 --- a/shaders/glsl/raytracinggltf/closesthit.rchit +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 460 - -#extension GL_EXT_ray_tracing : require -#extension GL_GOOGLE_include_directive : require -#extension GL_EXT_nonuniform_qualifier : require -#extension GL_EXT_buffer_reference2 : require -#extension GL_EXT_scalar_block_layout : require -#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require - -layout(location = 0) rayPayloadInEXT vec3 hitValue; -layout(location = 2) rayPayloadEXT bool shadowed; -hitAttributeEXT vec2 attribs; - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 3, set = 0) uniform sampler2D image; - -struct GeometryNode { - uint64_t vertexBufferDeviceAddress; - uint64_t indexBufferDeviceAddress; - int textureIndexBaseColor; - int textureIndexOcclusion; -}; -layout(binding = 4, set = 0) buffer GeometryNodes { GeometryNode nodes[]; } geometryNodes; - -layout(binding = 5, set = 0) uniform sampler2D textures[]; - -#include "bufferreferences.glsl" -#include "geometrytypes.glsl" - -void main() -{ - Triangle tri = unpackTriangle(gl_PrimitiveID, 112); - hitValue = vec3(tri.normal); - - GeometryNode geometryNode = geometryNodes.nodes[gl_GeometryIndexEXT]; - - vec3 color = texture(textures[nonuniformEXT(geometryNode.textureIndexBaseColor)], tri.uv).rgb; - if (geometryNode.textureIndexOcclusion > -1) { - float occlusion = texture(textures[nonuniformEXT(geometryNode.textureIndexOcclusion)], tri.uv).r; - color *= occlusion; - } - - hitValue = color; - - // Shadow casting - float tmin = 0.001; - float tmax = 10000.0; - float epsilon = 0.001; - vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT + tri.normal * epsilon; - shadowed = true; - vec3 lightVector = vec3(-5.0, -2.5, -5.0); - // Trace shadow ray and offset indices to match shadow hit/miss shader group indices -// traceRayEXT(topLevelAS, gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT, 0xFF, 0, 0, 1, origin, tmin, lightVector, tmax, 2); -// if (shadowed) { -// hitValue *= 0.7; -// } -} diff --git a/shaders/glsl/raytracinggltf/closesthit.rchit.spv b/shaders/glsl/raytracinggltf/closesthit.rchit.spv deleted file mode 100644 index 0fb5193b..00000000 Binary files a/shaders/glsl/raytracinggltf/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/glsl/raytracinggltf/geometrytypes.glsl b/shaders/glsl/raytracinggltf/geometrytypes.glsl deleted file mode 100644 index cfff9f14..00000000 --- a/shaders/glsl/raytracinggltf/geometrytypes.glsl +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Vertex -{ - vec3 pos; - vec3 normal; - vec2 uv; -}; - -struct Triangle { - Vertex vertices[3]; - vec3 normal; - vec2 uv; -}; - -// This function will unpack our vertex buffer data into a single triangle and calculates uv coordinates -Triangle unpackTriangle(uint index, int vertexSize) { - Triangle tri; - const uint triIndex = index * 3; - - GeometryNode geometryNode = geometryNodes.nodes[gl_GeometryIndexEXT]; - - Indices indices = Indices(geometryNode.indexBufferDeviceAddress); - Vertices vertices = Vertices(geometryNode.vertexBufferDeviceAddress); - - // Unpack vertices - // Data is packed as vec4 so we can map to the glTF vertex structure from the host side - // We match vkglTF::Vertex: pos.xyz+normal.x, normalyz+uv.xy - // glm::vec3 pos; - // glm::vec3 normal; - // glm::vec2 uv; - // ... - for (uint i = 0; i < 3; i++) { - const uint offset = indices.i[triIndex + i] * 6; - vec4 d0 = vertices.v[offset + 0]; // pos.xyz, n.x - vec4 d1 = vertices.v[offset + 1]; // n.yz, uv.xy - tri.vertices[i].pos = d0.xyz; - tri.vertices[i].normal = vec3(d0.w, d1.xy); - tri.vertices[i].uv = d1.zw; - } - // Calculate values at barycentric coordinates - vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y); - tri.uv = tri.vertices[0].uv * barycentricCoords.x + tri.vertices[1].uv * barycentricCoords.y + tri.vertices[2].uv * barycentricCoords.z; - tri.normal = tri.vertices[0].normal * barycentricCoords.x + tri.vertices[1].normal * barycentricCoords.y + tri.vertices[2].normal * barycentricCoords.z; - return tri; -} \ No newline at end of file diff --git a/shaders/glsl/raytracinggltf/miss.rmiss b/shaders/glsl/raytracinggltf/miss.rmiss deleted file mode 100644 index dacf6eac..00000000 --- a/shaders/glsl/raytracinggltf/miss.rmiss +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 460 -#extension GL_EXT_ray_tracing : enable - -layout(location = 0) rayPayloadInEXT vec3 hitValue; - -void main() -{ - hitValue = vec3(1.0); -} \ No newline at end of file diff --git a/shaders/glsl/raytracinggltf/miss.rmiss.spv b/shaders/glsl/raytracinggltf/miss.rmiss.spv deleted file mode 100644 index 6c508af2..00000000 Binary files a/shaders/glsl/raytracinggltf/miss.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracinggltf/random.glsl b/shaders/glsl/raytracinggltf/random.glsl deleted file mode 100644 index f35e62c1..00000000 --- a/shaders/glsl/raytracinggltf/random.glsl +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -// Tiny Encryption Algorithm -// By Fahad Zafar, Marc Olano and Aaron Curtis, see https://www.highperformancegraphics.org/previous/www_2010/media/GPUAlgorithms/HPG2010_GPUAlgorithms_Zafar.pdf -uint tea(uint val0, uint val1) -{ - uint sum = 0; - uint v0 = val0; - uint v1 = val1; - for (uint n = 0; n < 16; n++) - { - sum += 0x9E3779B9; - v0 += ((v1 << 4) + 0xA341316C) ^ (v1 + sum) ^ ((v1 >> 5) + 0xC8013EA4); - v1 += ((v0 << 4) + 0xAD90777D) ^ (v0 + sum) ^ ((v0 >> 5) + 0x7E95761E); - } - return v0; -} - -// Linear congruential generator based on the previous RNG state -// See https://en.wikipedia.org/wiki/Linear_congruential_generator -uint lcg(inout uint previous) -{ - const uint multiplier = 1664525u; - const uint increment = 1013904223u; - previous = (multiplier * previous + increment); - return previous & 0x00FFFFFF; -} - -// Generate a random float in [0, 1) given the previous RNG state -float rnd(inout uint previous) -{ - return (float(lcg(previous)) / float(0x01000000)); -} \ No newline at end of file diff --git a/shaders/glsl/raytracinggltf/raygen.rgen b/shaders/glsl/raytracinggltf/raygen.rgen deleted file mode 100644 index e3b47295..00000000 --- a/shaders/glsl/raytracinggltf/raygen.rgen +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 460 -#extension GL_EXT_ray_tracing : enable -#extension GL_GOOGLE_include_directive : require - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 1, set = 0, rgba8) uniform image2D image; -layout(binding = 2, set = 0) uniform CameraProperties -{ - mat4 viewInverse; - mat4 projInverse; - uint frame; -} cam; - -layout(location = 0) rayPayloadEXT vec3 hitValue; -layout(location = 3) rayPayloadEXT uint payloadSeed; - -#include "random.glsl" - -void main() -{ - uint seed = tea(gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x, cam.frame); - - float r1 = rnd(seed); - float r2 = rnd(seed); - - // Subpixel jitter: send the ray through a different position inside the pixel - // each time, to provide antialiasing. - vec2 subpixel_jitter = cam.frame == 0 ? vec2(0.5f, 0.5f) : vec2(r1, r2); - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + subpixel_jitter; - const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; - -// const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); -// const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); -// vec2 d = inUV * 2.0 - 1.0; - - vec4 origin = cam.viewInverse * vec4(0,0,0,1); - vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ; - vec4 direction = cam.viewInverse*vec4(normalize(target.xyz), 0.0) ; - - float tmin = 0.001; - float tmax = 10000.0; - - hitValue = vec3(0.0); - vec3 hitValues = vec3(0); - - const int samples = 4; - - // Trace multiple rays for e.g. transparency - for(int smpl = 0; smpl < samples; smpl++) { - payloadSeed = tea(gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x, cam.frame); - traceRayEXT(topLevelAS, gl_RayFlagsNoneEXT, 0xff, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0); - hitValues += hitValue; - } - -// imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValues / float(samples), 0.0)); - - vec3 hitVal = hitValues / float(samples); - - if(cam.frame > 0) - { - float a = 1.0f / float(cam.frame + 1); - vec3 old_color = imageLoad(image, ivec2(gl_LaunchIDEXT.xy)).xyz; - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(mix(old_color, hitVal, a), 1.f)); - } - else - { - // First frame, replace the value in the buffer - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitVal, 1.f)); - } -} diff --git a/shaders/glsl/raytracinggltf/raygen.rgen.spv b/shaders/glsl/raytracinggltf/raygen.rgen.spv deleted file mode 100644 index 6ad71428..00000000 Binary files a/shaders/glsl/raytracinggltf/raygen.rgen.spv and /dev/null differ diff --git a/shaders/glsl/raytracinggltf/shadow.rmiss b/shaders/glsl/raytracinggltf/shadow.rmiss deleted file mode 100644 index 36d9b7ba..00000000 --- a/shaders/glsl/raytracinggltf/shadow.rmiss +++ /dev/null @@ -1,9 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require - -layout(location = 2) rayPayloadInEXT bool shadowed; - -void main() -{ - shadowed = false; -} \ No newline at end of file diff --git a/shaders/glsl/raytracinggltf/shadow.rmiss.spv b/shaders/glsl/raytracinggltf/shadow.rmiss.spv deleted file mode 100644 index 9026dbea..00000000 Binary files a/shaders/glsl/raytracinggltf/shadow.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracingintersection/closesthit.rchit b/shaders/glsl/raytracingintersection/closesthit.rchit deleted file mode 100644 index 59cff6bb..00000000 --- a/shaders/glsl/raytracingintersection/closesthit.rchit +++ /dev/null @@ -1,35 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require -#extension GL_EXT_nonuniform_qualifier : enable - -layout(location = 0) rayPayloadInEXT vec3 hitValue; -layout(location = 2) rayPayloadEXT bool shadowed; -hitAttributeEXT vec2 attribs; - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 2, set = 0) uniform UBO -{ - mat4 viewInverse; - mat4 projInverse; - vec4 lightPos; -} ubo; - -struct Sphere { - vec3 center; - float radius; - vec4 color; -}; -layout(binding = 3, set = 0) buffer Spheres { Sphere s[]; } spheres; - -void main() -{ - Sphere sphere = spheres.s[gl_PrimitiveID]; - - vec3 worldPos = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT; - vec3 worldNrm = normalize(worldPos - sphere.center); - - // Basic lighting - vec3 lightVector = normalize(ubo.lightPos.xyz); - float dot_product = max(dot(lightVector, worldNrm), 0.2); - hitValue = sphere.color.rgb * dot_product; -} \ No newline at end of file diff --git a/shaders/glsl/raytracingintersection/closesthit.rchit.spv b/shaders/glsl/raytracingintersection/closesthit.rchit.spv deleted file mode 100644 index b956e8a6..00000000 Binary files a/shaders/glsl/raytracingintersection/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/glsl/raytracingintersection/intersection.rint b/shaders/glsl/raytracingintersection/intersection.rint deleted file mode 100644 index e2d4c410..00000000 --- a/shaders/glsl/raytracingintersection/intersection.rint +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 460 -#extension GL_EXT_ray_tracing : require - -struct Sphere { - vec3 center; - float radius; - vec4 color; -}; -layout(binding = 3, set = 0) buffer Spheres { Sphere s[]; } spheres; - -// Ray-sphere intersection -// By Inigo Quilez, from https://iquilezles.org/articles/spherefunctions/ -float sphIntersect(const Sphere s, vec3 ro, vec3 rd) -{ - vec3 oc = ro - s.center; - float b = dot(oc, rd); - float c = dot(oc, oc) - s.radius * s.radius; - float h = b * b - c; - if (h < 0.0) { - return -1.0; - } - h = sqrt(h); - return -b - h; -} - -void main() { - Sphere sphere = spheres.s[gl_PrimitiveID]; - float hit = sphIntersect(sphere, gl_WorldRayOriginEXT, gl_WorldRayDirectionEXT); - - if (hit > 0) { - reportIntersectionEXT(hit, 0); - } -} \ No newline at end of file diff --git a/shaders/glsl/raytracingintersection/intersection.rint.spv b/shaders/glsl/raytracingintersection/intersection.rint.spv deleted file mode 100644 index 29e50d65..00000000 Binary files a/shaders/glsl/raytracingintersection/intersection.rint.spv and /dev/null differ diff --git a/shaders/glsl/raytracingintersection/miss.rmiss b/shaders/glsl/raytracingintersection/miss.rmiss deleted file mode 100644 index 577f7e8e..00000000 --- a/shaders/glsl/raytracingintersection/miss.rmiss +++ /dev/null @@ -1,9 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require - -layout(location = 0) rayPayloadInEXT vec3 hitValue; - -void main() -{ - hitValue = vec3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingintersection/miss.rmiss.spv b/shaders/glsl/raytracingintersection/miss.rmiss.spv deleted file mode 100644 index 88ae284c..00000000 Binary files a/shaders/glsl/raytracingintersection/miss.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracingintersection/raygen.rgen b/shaders/glsl/raytracingintersection/raygen.rgen deleted file mode 100644 index 88b5f3fe..00000000 --- a/shaders/glsl/raytracingintersection/raygen.rgen +++ /dev/null @@ -1,33 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 1, set = 0, rgba8) uniform image2D image; -layout(binding = 2, set = 0) uniform CameraProperties -{ - mat4 viewInverse; - mat4 projInverse; - vec4 lightPos; -} cam; - -layout(location = 0) rayPayloadEXT vec3 hitValue; - -void main() -{ - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; - - vec4 origin = cam.viewInverse * vec4(0,0,0,1); - vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ; - vec4 direction = cam.viewInverse*vec4(normalize(target.xyz / target.w), 0) ; - - uint rayFlags = gl_RayFlagsOpaqueEXT; - uint cullMask = 0xff; - float tmin = 0.001; - float tmax = 10000.0; - - traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0); - - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue, 0.0)); -} diff --git a/shaders/glsl/raytracingintersection/raygen.rgen.spv b/shaders/glsl/raytracingintersection/raygen.rgen.spv deleted file mode 100644 index 012d3599..00000000 Binary files a/shaders/glsl/raytracingintersection/raygen.rgen.spv and /dev/null differ diff --git a/shaders/glsl/raytracingpositionfetch/closesthit.rchit b/shaders/glsl/raytracingpositionfetch/closesthit.rchit deleted file mode 100644 index 9043189c..00000000 --- a/shaders/glsl/raytracingpositionfetch/closesthit.rchit +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2024, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 460 -#extension GL_EXT_ray_tracing : enable -#extension GL_EXT_nonuniform_qualifier : enable -// This extension is required for fetching position data in the closes hit shader -#extension GL_EXT_ray_tracing_position_fetch : require - -layout(location = 0) rayPayloadInEXT vec3 hitValue; -hitAttributeEXT vec2 attribs; - -layout(binding = 2, set = 0) uniform UBO -{ - mat4 viewInverse; - mat4 projInverse; - vec4 lightPos; -} ubo; - -void main() -{ - // We need the barycentric coordinates to calculate data for the current position - const vec3 barycentricCoords = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y); - - // With VK_KHR_ray_tracing_position_fetch we can access the vertices for the hit triangle in the shader - vec3 vertexPos0 = gl_HitTriangleVertexPositionsEXT[0]; - vec3 vertexPos1 = gl_HitTriangleVertexPositionsEXT[1]; - vec3 vertexPos2 = gl_HitTriangleVertexPositionsEXT[2]; - vec3 currentPos = vertexPos0 * barycentricCoords.x + vertexPos1 * barycentricCoords.y + vertexPos2 * barycentricCoords.z; - - // Calcualte the normal from above values - vec3 normal = normalize(cross(vertexPos1 - vertexPos0, vertexPos2 - vertexPos0)); - normal = normalize(vec3(normal * gl_WorldToObjectEXT)); - - // Visualize the normal - hitValue = normal; - - // Basic lighting - vec3 lightDir = normalize(ubo.lightPos.xyz - currentPos); - float diffuse = max(dot(normal, lightDir), 0.0); - - hitValue = vec3(0.1 + diffuse); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingpositionfetch/closesthit.rchit.spv b/shaders/glsl/raytracingpositionfetch/closesthit.rchit.spv deleted file mode 100644 index 4a6f3184..00000000 Binary files a/shaders/glsl/raytracingpositionfetch/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/glsl/raytracingpositionfetch/miss.rmiss b/shaders/glsl/raytracingpositionfetch/miss.rmiss deleted file mode 100644 index 9e16c10d..00000000 --- a/shaders/glsl/raytracingpositionfetch/miss.rmiss +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (c) 2024, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 460 -#extension GL_EXT_ray_tracing : enable - -layout(location = 0) rayPayloadInEXT vec3 hitValue; - -void main() -{ - hitValue = vec3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingpositionfetch/miss.rmiss.spv b/shaders/glsl/raytracingpositionfetch/miss.rmiss.spv deleted file mode 100644 index 88ae284c..00000000 Binary files a/shaders/glsl/raytracingpositionfetch/miss.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracingpositionfetch/raygen.rgen b/shaders/glsl/raytracingpositionfetch/raygen.rgen deleted file mode 100644 index bd57ee2d..00000000 --- a/shaders/glsl/raytracingpositionfetch/raygen.rgen +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2024, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 460 -#extension GL_EXT_ray_tracing : enable - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 1, set = 0, rgba8) uniform image2D image; -layout(binding = 2, set = 0) uniform CameraProperties -{ - mat4 viewInverse; - mat4 projInverse; - vec4 lightPos; -} ubo; - -layout(location = 0) rayPayloadEXT vec3 hitValue; - -void main() -{ - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; - - vec4 origin = ubo.viewInverse * vec4(0,0,0,1); - vec4 target = ubo.projInverse * vec4(d.x, d.y, 1, 1) ; - vec4 direction = ubo.viewInverse*vec4(normalize(target.xyz), 0) ; - - float tmin = 0.001; - float tmax = 10000.0; - - hitValue = vec3(0.0); - - traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0); - - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue, 0.0)); -} diff --git a/shaders/glsl/raytracingpositionfetch/raygen.rgen.spv b/shaders/glsl/raytracingpositionfetch/raygen.rgen.spv deleted file mode 100644 index 338a06ec..00000000 Binary files a/shaders/glsl/raytracingpositionfetch/raygen.rgen.spv and /dev/null differ diff --git a/shaders/glsl/raytracingreflections/closesthit.rchit b/shaders/glsl/raytracingreflections/closesthit.rchit deleted file mode 100644 index 301686c7..00000000 --- a/shaders/glsl/raytracingreflections/closesthit.rchit +++ /dev/null @@ -1,76 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require -#extension GL_EXT_nonuniform_qualifier : enable - -struct RayPayload { - vec3 color; - float distance; - vec3 normal; - float reflector; -}; - -layout(location = 0) rayPayloadInEXT RayPayload rayPayload; - -hitAttributeEXT vec2 attribs; - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 2, set = 0) uniform UBO -{ - mat4 viewInverse; - mat4 projInverse; - vec4 lightPos; - int vertexSize; -} ubo; -layout(binding = 3, set = 0) buffer Vertices { vec4 v[]; } vertices; -layout(binding = 4, set = 0) buffer Indices { uint i[]; } indices; - -struct Vertex -{ - vec3 pos; - vec3 normal; - vec2 uv; - vec4 color; - vec4 _pad0; - vec4 _pad1; -}; - -Vertex unpack(uint index) -{ - // Unpack the vertices from the SSBO using the glTF vertex structure - // The multiplier is the size of the vertex divided by four float components (=16 bytes) - const int m = ubo.vertexSize / 16; - - vec4 d0 = vertices.v[m * index + 0]; - vec4 d1 = vertices.v[m * index + 1]; - vec4 d2 = vertices.v[m * index + 2]; - - Vertex v; - v.pos = d0.xyz; - v.normal = vec3(d0.w, d1.x, d1.y); - v.color = vec4(d2.x, d2.y, d2.z, 1.0); - - return v; -} - -void main() -{ - ivec3 index = ivec3(indices.i[3 * gl_PrimitiveID], indices.i[3 * gl_PrimitiveID + 1], indices.i[3 * gl_PrimitiveID + 2]); - - Vertex v0 = unpack(index.x); - Vertex v1 = unpack(index.y); - Vertex v2 = unpack(index.z); - - // Interpolate normal - const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y); - vec3 normal = normalize(v0.normal * barycentricCoords.x + v1.normal * barycentricCoords.y + v2.normal * barycentricCoords.z); - - // Basic lighting - vec3 lightVector = normalize(ubo.lightPos.xyz); - float dot_product = max(dot(lightVector, normal), 0.6); - rayPayload.color = v0.color.rgb * vec3(dot_product); - rayPayload.distance = gl_RayTmaxEXT; - rayPayload.normal = normal; - - // Objects with full white vertex color are treated as reflectors - rayPayload.reflector = ((v0.color.r == 1.0f) && (v0.color.g == 1.0f) && (v0.color.b == 1.0f)) ? 1.0f : 0.0f; -} diff --git a/shaders/glsl/raytracingreflections/closesthit.rchit.spv b/shaders/glsl/raytracingreflections/closesthit.rchit.spv deleted file mode 100644 index 148540f3..00000000 Binary files a/shaders/glsl/raytracingreflections/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/glsl/raytracingreflections/miss.rmiss b/shaders/glsl/raytracingreflections/miss.rmiss deleted file mode 100644 index f2da7971..00000000 --- a/shaders/glsl/raytracingreflections/miss.rmiss +++ /dev/null @@ -1,25 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require - -struct RayPayload { - vec3 color; - float distance; - vec3 normal; - float reflector; -}; - -layout(location = 0) rayPayloadInEXT RayPayload rayPayload; - -void main() -{ - // View-independent background gradient to simulate a basic sky background - const vec3 gradientStart = vec3(0.5, 0.6, 1.0); - const vec3 gradientEnd = vec3(1.0); - vec3 unitDir = normalize(gl_WorldRayDirectionEXT); - float t = 0.5 * (unitDir.y + 1.0); - rayPayload.color = (1.0-t) * gradientStart + t * gradientEnd; - - rayPayload.distance = -1.0f; - rayPayload.normal = vec3(0.0f); - rayPayload.reflector = 0.0f; -} \ No newline at end of file diff --git a/shaders/glsl/raytracingreflections/miss.rmiss.spv b/shaders/glsl/raytracingreflections/miss.rmiss.spv deleted file mode 100644 index c168cc39..00000000 Binary files a/shaders/glsl/raytracingreflections/miss.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracingreflections/raygen.rgen b/shaders/glsl/raytracingreflections/raygen.rgen deleted file mode 100644 index b1e6b63d..00000000 --- a/shaders/glsl/raytracingreflections/raygen.rgen +++ /dev/null @@ -1,62 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 1, set = 0, rgba8) uniform image2D image; -layout(binding = 2, set = 0) uniform CameraProperties -{ - mat4 viewInverse; - mat4 projInverse; - vec4 lightPos; -} cam; - - -struct RayPayload { - vec3 color; - float distance; - vec3 normal; - float reflector; -}; - -layout(location = 0) rayPayloadEXT RayPayload rayPayload; - -// Max. number of recursion is passed via a specialization constant -layout (constant_id = 0) const int MAX_RECURSION = 0; - -void main() -{ - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; - - vec4 origin = cam.viewInverse * vec4(0,0,0,1); - vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ; - vec4 direction = cam.viewInverse*vec4(normalize(target.xyz / target.w), 0); - - uint rayFlags = gl_RayFlagsOpaqueEXT; - uint cullMask = 0xff; - float tmin = 0.001; - float tmax = 10000.0; - - vec3 color = vec3(0.0); - - for (int i = 0; i < MAX_RECURSION; i++) { - traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0); - vec3 hitColor = rayPayload.color; - - if (rayPayload.distance < 0.0f) { - color += hitColor; - break; - } else if (rayPayload.reflector == 1.0f) { - const vec4 hitPos = origin + direction * rayPayload.distance; - origin.xyz = hitPos.xyz + rayPayload.normal * 0.001f; - direction.xyz = reflect(direction.xyz, rayPayload.normal); - } else { - color += hitColor; - break; - } - - } - - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(color, 0.0)); -} diff --git a/shaders/glsl/raytracingreflections/raygen.rgen.spv b/shaders/glsl/raytracingreflections/raygen.rgen.spv deleted file mode 100644 index 7e2b2d3c..00000000 Binary files a/shaders/glsl/raytracingreflections/raygen.rgen.spv and /dev/null differ diff --git a/shaders/glsl/raytracingsbtdata/closesthit.rchit b/shaders/glsl/raytracingsbtdata/closesthit.rchit deleted file mode 100644 index 17e642a1..00000000 --- a/shaders/glsl/raytracingsbtdata/closesthit.rchit +++ /dev/null @@ -1,19 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : enable -#extension GL_EXT_nonuniform_qualifier : enable - -layout(location = 0) rayPayloadInEXT vec3 hitValue; -hitAttributeEXT vec2 attribs; - -layout(shaderRecordEXT, std430) buffer SBT { - float r; - float g; - float b; -}; - -void main() -{ - // Update the hit value to the hit record SBT data associated with this - // geometry ID and ray ID - hitValue = vec3(r, g, b); -} diff --git a/shaders/glsl/raytracingsbtdata/closesthit.rchit.spv b/shaders/glsl/raytracingsbtdata/closesthit.rchit.spv deleted file mode 100644 index 5f0cbc7b..00000000 Binary files a/shaders/glsl/raytracingsbtdata/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/glsl/raytracingsbtdata/miss.rmiss b/shaders/glsl/raytracingsbtdata/miss.rmiss deleted file mode 100644 index 36eb1b4b..00000000 --- a/shaders/glsl/raytracingsbtdata/miss.rmiss +++ /dev/null @@ -1,17 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : enable - -layout(location = 0) rayPayloadInEXT vec3 hitValue; - -layout(shaderRecordEXT, std430) buffer SBT { - float r; - float g; - float b; -}; - -void main() -{ - // Update the hit value to the hit record SBT data associated with this - // miss record - hitValue = vec3(r, g, b); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingsbtdata/miss.rmiss.spv b/shaders/glsl/raytracingsbtdata/miss.rmiss.spv deleted file mode 100644 index 8c74f346..00000000 Binary files a/shaders/glsl/raytracingsbtdata/miss.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracingsbtdata/raygen.rgen b/shaders/glsl/raytracingsbtdata/raygen.rgen deleted file mode 100644 index 42282dab..00000000 --- a/shaders/glsl/raytracingsbtdata/raygen.rgen +++ /dev/null @@ -1,52 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : enable - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 1, set = 0, rgba8) uniform image2D image; -layout(binding = 2, set = 0) uniform CameraProperties -{ - mat4 viewInverse; - mat4 projInverse; -} cam; - -layout(location = 0) rayPayloadEXT vec3 hitValue; - -layout(shaderRecordEXT, std430) buffer SBT { - float r; - float g; - float b; -}; - -void main() -{ - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; - - vec4 origin = cam.viewInverse * vec4(0,0,0,1); - vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ; - vec4 direction = cam.viewInverse*vec4(normalize(target.xyz), 0) ; - - float tmin = 0.001; - float tmax = 10000.0; - - // use border to demonstrate raygen record data - if (all(greaterThan(gl_LaunchIDEXT.xy, ivec2(16, 16))) && all(lessThan(gl_LaunchIDEXT.xy, gl_LaunchSizeEXT.xy - ivec2(16, 16)))) - { - // Generate a checker board pattern to trace out rays or use hit record data - ivec2 pos = ivec2(gl_LaunchIDEXT / 16); - if (((pos.x + pos.y % 2) % 2) == 0) { - // This will set hit value to either hit or miss SBT record color - traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0); - } - else { - // Set the hit value to the raygen SBT data - hitValue = vec3(r, g, b); - } - } - else { - // Set hit value to black - hitValue = vec3(0.0, 0.0, 0.0); - } - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue, 0.0)); -} diff --git a/shaders/glsl/raytracingsbtdata/raygen.rgen.spv b/shaders/glsl/raytracingsbtdata/raygen.rgen.spv deleted file mode 100644 index 2f4da420..00000000 Binary files a/shaders/glsl/raytracingsbtdata/raygen.rgen.spv and /dev/null differ diff --git a/shaders/glsl/raytracingshadows/closesthit.rchit b/shaders/glsl/raytracingshadows/closesthit.rchit deleted file mode 100644 index 7026fcab..00000000 --- a/shaders/glsl/raytracingshadows/closesthit.rchit +++ /dev/null @@ -1,75 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require -#extension GL_EXT_nonuniform_qualifier : enable - -layout(location = 0) rayPayloadInEXT vec3 hitValue; -layout(location = 2) rayPayloadEXT bool shadowed; -hitAttributeEXT vec2 attribs; - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 2, set = 0) uniform UBO -{ - mat4 viewInverse; - mat4 projInverse; - vec4 lightPos; - int vertexSize; -} ubo; -layout(binding = 3, set = 0) buffer Vertices { vec4 v[]; } vertices; -layout(binding = 4, set = 0) buffer Indices { uint i[]; } indices; - -struct Vertex -{ - vec3 pos; - vec3 normal; - vec2 uv; - vec4 color; - vec4 _pad0; - vec4 _pad1; - }; - -Vertex unpack(uint index) -{ - // Unpack the vertices from the SSBO using the glTF vertex structure - // The multiplier is the size of the vertex divided by four float components (=16 bytes) - const int m = ubo.vertexSize / 16; - - vec4 d0 = vertices.v[m * index + 0]; - vec4 d1 = vertices.v[m * index + 1]; - vec4 d2 = vertices.v[m * index + 2]; - - Vertex v; - v.pos = d0.xyz; - v.normal = vec3(d0.w, d1.x, d1.y); - v.color = vec4(d2.x, d2.y, d2.z, 1.0); - - return v; -} - -void main() -{ - ivec3 index = ivec3(indices.i[3 * gl_PrimitiveID], indices.i[3 * gl_PrimitiveID + 1], indices.i[3 * gl_PrimitiveID + 2]); - - Vertex v0 = unpack(index.x); - Vertex v1 = unpack(index.y); - Vertex v2 = unpack(index.z); - - // Interpolate normal - const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y); - vec3 normal = normalize(v0.normal * barycentricCoords.x + v1.normal * barycentricCoords.y + v2.normal * barycentricCoords.z); - - // Basic lighting - vec3 lightVector = normalize(ubo.lightPos.xyz); - float dot_product = max(dot(lightVector, normal), 0.2); - hitValue = v0.color.rgb * dot_product; - - // Shadow casting - float tmin = 0.001; - float tmax = 10000.0; - vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT; - shadowed = true; - // Trace shadow ray and offset indices to match shadow hit/miss shader group indices - traceRayEXT(topLevelAS, gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT, 0xFF, 0, 0, 1, origin, tmin, lightVector, tmax, 2); - if (shadowed) { - hitValue *= 0.3; - } -} \ No newline at end of file diff --git a/shaders/glsl/raytracingshadows/closesthit.rchit.spv b/shaders/glsl/raytracingshadows/closesthit.rchit.spv deleted file mode 100644 index 92b2b6d7..00000000 Binary files a/shaders/glsl/raytracingshadows/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/glsl/raytracingshadows/miss.rmiss b/shaders/glsl/raytracingshadows/miss.rmiss deleted file mode 100644 index 577f7e8e..00000000 --- a/shaders/glsl/raytracingshadows/miss.rmiss +++ /dev/null @@ -1,9 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require - -layout(location = 0) rayPayloadInEXT vec3 hitValue; - -void main() -{ - hitValue = vec3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingshadows/miss.rmiss.spv b/shaders/glsl/raytracingshadows/miss.rmiss.spv deleted file mode 100644 index 58fb3309..00000000 Binary files a/shaders/glsl/raytracingshadows/miss.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracingshadows/raygen.rgen b/shaders/glsl/raytracingshadows/raygen.rgen deleted file mode 100644 index 88b5f3fe..00000000 --- a/shaders/glsl/raytracingshadows/raygen.rgen +++ /dev/null @@ -1,33 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 1, set = 0, rgba8) uniform image2D image; -layout(binding = 2, set = 0) uniform CameraProperties -{ - mat4 viewInverse; - mat4 projInverse; - vec4 lightPos; -} cam; - -layout(location = 0) rayPayloadEXT vec3 hitValue; - -void main() -{ - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; - - vec4 origin = cam.viewInverse * vec4(0,0,0,1); - vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ; - vec4 direction = cam.viewInverse*vec4(normalize(target.xyz / target.w), 0) ; - - uint rayFlags = gl_RayFlagsOpaqueEXT; - uint cullMask = 0xff; - float tmin = 0.001; - float tmax = 10000.0; - - traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0); - - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue, 0.0)); -} diff --git a/shaders/glsl/raytracingshadows/raygen.rgen.spv b/shaders/glsl/raytracingshadows/raygen.rgen.spv deleted file mode 100644 index 30ab96d6..00000000 Binary files a/shaders/glsl/raytracingshadows/raygen.rgen.spv and /dev/null differ diff --git a/shaders/glsl/raytracingshadows/shadow.rmiss b/shaders/glsl/raytracingshadows/shadow.rmiss deleted file mode 100644 index 36d9b7ba..00000000 --- a/shaders/glsl/raytracingshadows/shadow.rmiss +++ /dev/null @@ -1,9 +0,0 @@ -#version 460 -#extension GL_EXT_ray_tracing : require - -layout(location = 2) rayPayloadInEXT bool shadowed; - -void main() -{ - shadowed = false; -} \ No newline at end of file diff --git a/shaders/glsl/raytracingshadows/shadow.rmiss.spv b/shaders/glsl/raytracingshadows/shadow.rmiss.spv deleted file mode 100644 index 65b01ba9..00000000 Binary files a/shaders/glsl/raytracingshadows/shadow.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracingtextures/anyhit.rahit b/shaders/glsl/raytracingtextures/anyhit.rahit deleted file mode 100644 index eb85aa3a..00000000 --- a/shaders/glsl/raytracingtextures/anyhit.rahit +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ -#version 460 - -#extension GL_EXT_ray_tracing : require -#extension GL_GOOGLE_include_directive : require -#extension GL_EXT_nonuniform_qualifier : require -#extension GL_EXT_buffer_reference2 : require -#extension GL_EXT_scalar_block_layout : require -#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require - -hitAttributeEXT vec2 attribs; - -layout(binding = 3, set = 0) uniform sampler2D image; - -#include "bufferreferences.glsl" -#include "geometrytypes.glsl" - -void main() -{ - Triangle tri = unpackTriangle(gl_PrimitiveID, 32); - vec4 color = texture(image, tri.uv); - // If the alpha value of the texture at the current UV coordinates is below a given threshold, we'll ignore this intersection - // That way ray traversal will be stopped and the miss shader will be invoked - if (color.a < 0.9) { - ignoreIntersectionEXT; - } -} \ No newline at end of file diff --git a/shaders/glsl/raytracingtextures/anyhit.rahit.spv b/shaders/glsl/raytracingtextures/anyhit.rahit.spv deleted file mode 100644 index ac4bcc59..00000000 Binary files a/shaders/glsl/raytracingtextures/anyhit.rahit.spv and /dev/null differ diff --git a/shaders/glsl/raytracingtextures/bufferreferences.glsl b/shaders/glsl/raytracingtextures/bufferreferences.glsl deleted file mode 100644 index 6fa238ed..00000000 --- a/shaders/glsl/raytracingtextures/bufferreferences.glsl +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -layout(push_constant) uniform BufferReferences { - uint64_t vertices; - uint64_t indices; -} bufferReferences; - -layout(buffer_reference, scalar) buffer Vertices {vec4 v[]; }; -layout(buffer_reference, scalar) buffer Indices {uint i[]; }; \ No newline at end of file diff --git a/shaders/glsl/raytracingtextures/closesthit.rchit b/shaders/glsl/raytracingtextures/closesthit.rchit deleted file mode 100644 index b852d968..00000000 --- a/shaders/glsl/raytracingtextures/closesthit.rchit +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 460 - -#extension GL_EXT_ray_tracing : require -#extension GL_GOOGLE_include_directive : require -#extension GL_EXT_nonuniform_qualifier : require -#extension GL_EXT_buffer_reference2 : require -#extension GL_EXT_scalar_block_layout : require -#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require - -layout(location = 0) rayPayloadInEXT vec3 hitValue; -hitAttributeEXT vec2 attribs; - -layout(binding = 3, set = 0) uniform sampler2D image; - -#include "bufferreferences.glsl" -#include "geometrytypes.glsl" - -void main() -{ - Triangle tri = unpackTriangle(gl_PrimitiveID, 32); - hitValue = vec3(tri.uv, 0.0f); - // Fetch the color for this ray hit from the texture at the current uv coordinates - vec4 color = texture(image, tri.uv); - hitValue = color.rgb; -} diff --git a/shaders/glsl/raytracingtextures/closesthit.rchit.spv b/shaders/glsl/raytracingtextures/closesthit.rchit.spv deleted file mode 100644 index 7c950d27..00000000 Binary files a/shaders/glsl/raytracingtextures/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/glsl/raytracingtextures/geometrytypes.glsl b/shaders/glsl/raytracingtextures/geometrytypes.glsl deleted file mode 100644 index 408dcce1..00000000 --- a/shaders/glsl/raytracingtextures/geometrytypes.glsl +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Vertex -{ - vec3 pos; - vec2 uv; -}; - -struct Triangle { - Vertex vertices[3]; - vec2 uv; -}; - -// This function will unpack our vertex buffer data into a single triangle and calculates uv coordinates -Triangle unpackTriangle(uint index, int vertexSize) { - Triangle tri; - const uint triIndex = index * 3; - - Indices indices = Indices(bufferReferences.indices); - Vertices vertices = Vertices(bufferReferences.vertices); - - // Unpack vertices - // Data is packed as vec4 so we can map to the glTF vertex structure from the host side - for (uint i = 0; i < 3; i++) { - const uint offset = indices.i[triIndex + i] * (vertexSize / 16); - vec4 d0 = vertices.v[offset + 0]; // pos.xyz, n.x - vec4 d1 = vertices.v[offset + 1]; // n.yz, uv.xy - tri.vertices[i].pos = d0.xyz; - tri.vertices[i].uv = d1.zw; - } - // Calculate values at barycentric coordinates - vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y); - tri.uv = tri.vertices[0].uv * barycentricCoords.x + tri.vertices[1].uv * barycentricCoords.y + tri.vertices[2].uv * barycentricCoords.z; - return tri; -} \ No newline at end of file diff --git a/shaders/glsl/raytracingtextures/miss.rmiss b/shaders/glsl/raytracingtextures/miss.rmiss deleted file mode 100644 index 5165170c..00000000 --- a/shaders/glsl/raytracingtextures/miss.rmiss +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 460 -#extension GL_EXT_ray_tracing : enable - -layout(location = 0) rayPayloadInEXT vec3 hitValue; - -void main() -{ - hitValue = vec3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/glsl/raytracingtextures/miss.rmiss.spv b/shaders/glsl/raytracingtextures/miss.rmiss.spv deleted file mode 100644 index 88ae284c..00000000 Binary files a/shaders/glsl/raytracingtextures/miss.rmiss.spv and /dev/null differ diff --git a/shaders/glsl/raytracingtextures/raygen.rgen b/shaders/glsl/raytracingtextures/raygen.rgen deleted file mode 100644 index a3e99dc6..00000000 --- a/shaders/glsl/raytracingtextures/raygen.rgen +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#version 460 -#extension GL_EXT_ray_tracing : enable - -layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; -layout(binding = 1, set = 0, rgba8) uniform image2D image; -layout(binding = 2, set = 0) uniform CameraProperties -{ - mat4 viewInverse; - mat4 projInverse; -} cam; - -layout(location = 0) rayPayloadEXT vec3 hitValue; - -void main() -{ - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; - - vec4 origin = cam.viewInverse * vec4(0,0,0,1); - vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ; - vec4 direction = cam.viewInverse*vec4(normalize(target.xyz), 0) ; - - float tmin = 0.001; - float tmax = 10000.0; - - hitValue = vec3(0.0); - - traceRayEXT(topLevelAS, gl_RayFlagsNoneEXT, 0xff, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0); - - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue, 0.0)); -} diff --git a/shaders/glsl/raytracingtextures/raygen.rgen.spv b/shaders/glsl/raytracingtextures/raygen.rgen.spv deleted file mode 100644 index e39633f5..00000000 Binary files a/shaders/glsl/raytracingtextures/raygen.rgen.spv and /dev/null differ diff --git a/shaders/glsl/renderheadless/triangle.frag b/shaders/glsl/renderheadless/triangle.frag deleted file mode 100644 index f3e513b9..00000000 --- a/shaders/glsl/renderheadless/triangle.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = vec4(inColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/renderheadless/triangle.frag.spv b/shaders/glsl/renderheadless/triangle.frag.spv deleted file mode 100644 index f67f2011..00000000 Binary files a/shaders/glsl/renderheadless/triangle.frag.spv and /dev/null differ diff --git a/shaders/glsl/renderheadless/triangle.vert b/shaders/glsl/renderheadless/triangle.vert deleted file mode 100644 index b89716f4..00000000 --- a/shaders/glsl/renderheadless/triangle.vert +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inColor; - -layout (location = 0) out vec3 outColor; - -out gl_PerVertex { - vec4 gl_Position; -}; - -layout(push_constant) uniform PushConsts { - mat4 mvp; -} pushConsts; - -void main() -{ - outColor = inColor; - gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/renderheadless/triangle.vert.spv b/shaders/glsl/renderheadless/triangle.vert.spv deleted file mode 100644 index 94c1bb68..00000000 Binary files a/shaders/glsl/renderheadless/triangle.vert.spv and /dev/null differ diff --git a/shaders/glsl/screenshot/mesh.frag b/shaders/glsl/screenshot/mesh.frag deleted file mode 100644 index aab33e1d..00000000 --- a/shaders/glsl/screenshot/mesh.frag +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 ambient = vec3(0.1); - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); - outFragColor = vec4((ambient + diffuse) * inColor.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/screenshot/mesh.frag.spv b/shaders/glsl/screenshot/mesh.frag.spv deleted file mode 100644 index 33607eb7..00000000 Binary files a/shaders/glsl/screenshot/mesh.frag.spv and /dev/null differ diff --git a/shaders/glsl/screenshot/mesh.vert b/shaders/glsl/screenshot/mesh.vert deleted file mode 100644 index 91cbd6fb..00000000 --- a/shaders/glsl/screenshot/mesh.vert +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (set = 0, binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - gl_Position = ubo.projection * ubo.view * ubo.model * inPos; - - vec4 pos = ubo.view * ubo.model * vec4(inPos.xyz, 1.0); - outNormal = mat3(ubo.model) * inNormal; - - vec3 lightPos = vec3(1.0f, -1.0f, 1.0f); - outLightVec = lightPos.xyz - pos.xyz; - outViewVec = -pos.xyz; -} diff --git a/shaders/glsl/screenshot/mesh.vert.spv b/shaders/glsl/screenshot/mesh.vert.spv deleted file mode 100644 index 16742208..00000000 Binary files a/shaders/glsl/screenshot/mesh.vert.spv and /dev/null differ diff --git a/shaders/glsl/shaderobjects/phong.frag b/shaders/glsl/shaderobjects/phong.frag deleted file mode 100644 index b207e798..00000000 --- a/shaders/glsl/shaderobjects/phong.frag +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - // Desaturate color - vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65)); - - // High ambient colors because mesh materials are pretty dark - vec3 ambient = color * vec3(1.0); - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * color; - vec3 specular = pow(max(dot(R, V), 0.0), 32.0) * vec3(0.35); - outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/shaderobjects/phong.frag.spv b/shaders/glsl/shaderobjects/phong.frag.spv deleted file mode 100644 index d9fbe6c4..00000000 Binary files a/shaders/glsl/shaderobjects/phong.frag.spv and /dev/null differ diff --git a/shaders/glsl/shaderobjects/phong.vert b/shaders/glsl/shaderobjects/phong.vert deleted file mode 100644 index c0069072..00000000 --- a/shaders/glsl/shaderobjects/phong.vert +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(ubo.model) * inNormal; - vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/shaderobjects/phong.vert.spv b/shaders/glsl/shaderobjects/phong.vert.spv deleted file mode 100644 index b22327fb..00000000 Binary files a/shaders/glsl/shaderobjects/phong.vert.spv and /dev/null differ diff --git a/shaders/glsl/shadowmapping/offscreen.frag b/shaders/glsl/shadowmapping/offscreen.frag deleted file mode 100644 index 38d211d7..00000000 --- a/shaders/glsl/shadowmapping/offscreen.frag +++ /dev/null @@ -1,8 +0,0 @@ -#version 450 - -layout(location = 0) out vec4 color; - -void main() -{ - color = vec4(1.0, 0.0, 0.0, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/shadowmapping/offscreen.frag.spv b/shaders/glsl/shadowmapping/offscreen.frag.spv deleted file mode 100644 index 4caadfac..00000000 Binary files a/shaders/glsl/shadowmapping/offscreen.frag.spv and /dev/null differ diff --git a/shaders/glsl/shadowmapping/offscreen.vert b/shaders/glsl/shadowmapping/offscreen.vert deleted file mode 100644 index b20c695b..00000000 --- a/shaders/glsl/shadowmapping/offscreen.vert +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout (binding = 0) uniform UBO -{ - mat4 depthMVP; -} ubo; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - - -void main() -{ - gl_Position = ubo.depthMVP * vec4(inPos, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/shadowmapping/offscreen.vert.spv b/shaders/glsl/shadowmapping/offscreen.vert.spv deleted file mode 100644 index 8b456320..00000000 Binary files a/shaders/glsl/shadowmapping/offscreen.vert.spv and /dev/null differ diff --git a/shaders/glsl/shadowmapping/quad.frag b/shaders/glsl/shadowmapping/quad.frag deleted file mode 100644 index 86815ca7..00000000 --- a/shaders/glsl/shadowmapping/quad.frag +++ /dev/null @@ -1,32 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - mat4 lightSpace; - vec4 lightPos; - float zNear; - float zFar; -} ubo; - -float LinearizeDepth(float depth) -{ - float n = ubo.zNear; - float f = ubo.zFar; - float z = depth; - return (2.0 * n) / (f + n - z * (f - n)); -} - -void main() -{ - float depth = texture(samplerColor, inUV).r; - outFragColor = vec4(vec3(1.0-LinearizeDepth(depth)), 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/shadowmapping/quad.frag.spv b/shaders/glsl/shadowmapping/quad.frag.spv deleted file mode 100644 index 88c56a21..00000000 Binary files a/shaders/glsl/shadowmapping/quad.frag.spv and /dev/null differ diff --git a/shaders/glsl/shadowmapping/quad.vert b/shaders/glsl/shadowmapping/quad.vert deleted file mode 100644 index 3a42f3c5..00000000 --- a/shaders/glsl/shadowmapping/quad.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/shadowmapping/quad.vert.spv b/shaders/glsl/shadowmapping/quad.vert.spv deleted file mode 100644 index 822048d7..00000000 Binary files a/shaders/glsl/shadowmapping/quad.vert.spv and /dev/null differ diff --git a/shaders/glsl/shadowmapping/scene.frag b/shaders/glsl/shadowmapping/scene.frag deleted file mode 100644 index a8e67f56..00000000 --- a/shaders/glsl/shadowmapping/scene.frag +++ /dev/null @@ -1,66 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D shadowMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; -layout (location = 4) in vec4 inShadowCoord; - -layout (constant_id = 0) const int enablePCF = 0; - -layout (location = 0) out vec4 outFragColor; - -#define ambient 0.1 - -float textureProj(vec4 shadowCoord, vec2 off) -{ - float shadow = 1.0; - if ( shadowCoord.z > -1.0 && shadowCoord.z < 1.0 ) - { - float dist = texture( shadowMap, shadowCoord.st + off ).r; - if ( shadowCoord.w > 0.0 && dist < shadowCoord.z ) - { - shadow = ambient; - } - } - return shadow; -} - -float filterPCF(vec4 sc) -{ - ivec2 texDim = textureSize(shadowMap, 0); - float scale = 1.5; - float dx = scale * 1.0 / float(texDim.x); - float dy = scale * 1.0 / float(texDim.y); - - float shadowFactor = 0.0; - int count = 0; - int range = 1; - - for (int x = -range; x <= range; x++) - { - for (int y = -range; y <= range; y++) - { - shadowFactor += textureProj(sc, vec2(dx*x, dy*y)); - count++; - } - - } - return shadowFactor / count; -} - -void main() -{ - float shadow = (enablePCF == 1) ? filterPCF(inShadowCoord / inShadowCoord.w) : textureProj(inShadowCoord / inShadowCoord.w, vec2(0.0)); - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = normalize(-reflect(L, N)); - vec3 diffuse = max(dot(N, L), ambient) * inColor; - - outFragColor = vec4(diffuse * shadow, 1.0); - -} diff --git a/shaders/glsl/shadowmapping/scene.frag.spv b/shaders/glsl/shadowmapping/scene.frag.spv deleted file mode 100644 index 5f723ab7..00000000 Binary files a/shaders/glsl/shadowmapping/scene.frag.spv and /dev/null differ diff --git a/shaders/glsl/shadowmapping/scene.vert b/shaders/glsl/shadowmapping/scene.vert deleted file mode 100644 index 55bb5ea1..00000000 --- a/shaders/glsl/shadowmapping/scene.vert +++ /dev/null @@ -1,45 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - mat4 lightSpace; - vec4 lightPos; - float zNear; - float zFar; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; -layout (location = 4) out vec4 outShadowCoord; - -const mat4 biasMat = mat4( - 0.5, 0.0, 0.0, 0.0, - 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.5, 0.5, 0.0, 1.0 ); - -void main() -{ - outColor = inColor; - outNormal = inNormal; - - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(ubo.model) * inNormal; - outLightVec = normalize(ubo.lightPos.xyz - inPos); - outViewVec = -pos.xyz; - - outShadowCoord = ( biasMat * ubo.lightSpace * ubo.model ) * vec4(inPos, 1.0); -} - diff --git a/shaders/glsl/shadowmapping/scene.vert.spv b/shaders/glsl/shadowmapping/scene.vert.spv deleted file mode 100644 index 1782e100..00000000 Binary files a/shaders/glsl/shadowmapping/scene.vert.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingcascade/debugshadowmap.frag b/shaders/glsl/shadowmappingcascade/debugshadowmap.frag deleted file mode 100644 index 37bcad80..00000000 --- a/shaders/glsl/shadowmappingcascade/debugshadowmap.frag +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2DArray shadowMap; - -layout (location = 0) in vec2 inUV; -layout (location = 1) flat in uint inCascadeIndex; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - float depth = texture(shadowMap, vec3(inUV, float(inCascadeIndex))).r; - outFragColor = vec4(vec3((depth)), 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/shadowmappingcascade/debugshadowmap.frag.spv b/shaders/glsl/shadowmappingcascade/debugshadowmap.frag.spv deleted file mode 100644 index bd866c7a..00000000 Binary files a/shaders/glsl/shadowmappingcascade/debugshadowmap.frag.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingcascade/debugshadowmap.vert b/shaders/glsl/shadowmappingcascade/debugshadowmap.vert deleted file mode 100644 index 8db331f2..00000000 --- a/shaders/glsl/shadowmappingcascade/debugshadowmap.vert +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(push_constant) uniform PushConsts { - vec4 position; - uint cascadeIndex; -} pushConsts; - -layout (location = 0) out vec2 outUV; -layout (location = 1) out uint outCascadeIndex; - -out gl_PerVertex { - vec4 gl_Position; -}; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - outCascadeIndex = pushConsts.cascadeIndex; - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/shadowmappingcascade/debugshadowmap.vert.spv b/shaders/glsl/shadowmappingcascade/debugshadowmap.vert.spv deleted file mode 100644 index 3892ce43..00000000 Binary files a/shaders/glsl/shadowmappingcascade/debugshadowmap.vert.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingcascade/depthpass.frag b/shaders/glsl/shadowmappingcascade/depthpass.frag deleted file mode 100644 index 2e239363..00000000 --- a/shaders/glsl/shadowmappingcascade/depthpass.frag +++ /dev/null @@ -1,13 +0,0 @@ -#version 450 - -layout (set = 1, binding = 0) uniform sampler2D colorMap; - -layout (location = 0) in vec2 inUV; - -void main() -{ - float alpha = texture(colorMap, inUV).a; - if (alpha < 0.5) { - discard; - } -} \ No newline at end of file diff --git a/shaders/glsl/shadowmappingcascade/depthpass.frag.spv b/shaders/glsl/shadowmappingcascade/depthpass.frag.spv deleted file mode 100644 index 655cbbf3..00000000 Binary files a/shaders/glsl/shadowmappingcascade/depthpass.frag.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingcascade/depthpass.vert b/shaders/glsl/shadowmappingcascade/depthpass.vert deleted file mode 100644 index c4a0f7fd..00000000 --- a/shaders/glsl/shadowmappingcascade/depthpass.vert +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; - -// todo: pass via specialization constant -#define SHADOW_MAP_CASCADE_COUNT 4 - -layout(push_constant) uniform PushConsts { - vec4 position; - uint cascadeIndex; -} pushConsts; - -layout (set = 0, binding = 3) uniform UBO { - mat4[SHADOW_MAP_CASCADE_COUNT] cascadeViewProjMat; -} ubo; - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = inUV; - vec3 pos = inPos + pushConsts.position.xyz; - gl_Position = ubo.cascadeViewProjMat[pushConsts.cascadeIndex] * vec4(pos, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/shadowmappingcascade/depthpass.vert.spv b/shaders/glsl/shadowmappingcascade/depthpass.vert.spv deleted file mode 100644 index 2c6c5daf..00000000 Binary files a/shaders/glsl/shadowmappingcascade/depthpass.vert.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingcascade/scene.frag b/shaders/glsl/shadowmappingcascade/scene.frag deleted file mode 100644 index 9f33bed4..00000000 --- a/shaders/glsl/shadowmappingcascade/scene.frag +++ /dev/null @@ -1,126 +0,0 @@ -#version 450 - -#define SHADOW_MAP_CASCADE_COUNT 4 - -layout (set = 0, binding = 1) uniform sampler2DArray shadowMap; -layout (set = 1, binding = 0) uniform sampler2D colorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewPos; -layout (location = 3) in vec3 inPos; -layout (location = 4) in vec2 inUV; - -layout (constant_id = 0) const int enablePCF = 0; - -layout (location = 0) out vec4 outFragColor; - -#define ambient 0.3 - -layout (set = 0, binding = 2) uniform UBO { - vec4 cascadeSplits; - mat4 inverseViewMat; - vec3 lightDir; - float _pad; - int colorCascades; -} ubo; - -layout (set = 0, binding = 3) uniform CVPM { - mat4 matrices[SHADOW_MAP_CASCADE_COUNT]; -} cascadeViewProjMatrices; - -const mat4 biasMat = mat4( - 0.5, 0.0, 0.0, 0.0, - 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.5, 0.5, 0.0, 1.0 -); - -float textureProj(vec4 shadowCoord, vec2 offset, uint cascadeIndex) -{ - float shadow = 1.0; - float bias = 0.005; - - if ( shadowCoord.z > -1.0 && shadowCoord.z < 1.0 ) { - float dist = texture(shadowMap, vec3(shadowCoord.st + offset, cascadeIndex)).r; - if (shadowCoord.w > 0 && dist < shadowCoord.z - bias) { - shadow = ambient; - } - } - return shadow; - -} - -float filterPCF(vec4 sc, uint cascadeIndex) -{ - ivec2 texDim = textureSize(shadowMap, 0).xy; - float scale = 0.75; - float dx = scale * 1.0 / float(texDim.x); - float dy = scale * 1.0 / float(texDim.y); - - float shadowFactor = 0.0; - int count = 0; - int range = 1; - - for (int x = -range; x <= range; x++) { - for (int y = -range; y <= range; y++) { - shadowFactor += textureProj(sc, vec2(dx*x, dy*y), cascadeIndex); - count++; - } - } - return shadowFactor / count; -} - -void main() -{ - vec4 color = texture(colorMap, inUV); - if (color.a < 0.5) { - discard; - } - - // Get cascade index for the current fragment's view position - uint cascadeIndex = 0; - for(uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i) { - if(inViewPos.z < ubo.cascadeSplits[i]) { - cascadeIndex = i + 1; - } - } - - // Depth compare for shadowing - vec4 shadowCoord = (biasMat * cascadeViewProjMatrices.matrices[cascadeIndex]) * vec4(inPos, 1.0); - - float shadow = 0; - if (enablePCF == 1) { - shadow = filterPCF(shadowCoord / shadowCoord.w, cascadeIndex); - } else { - shadow = textureProj(shadowCoord / shadowCoord.w, vec2(0.0), cascadeIndex); - } - - // Directional light - vec3 N = normalize(inNormal); - vec3 L = normalize(-ubo.lightDir); - vec3 H = normalize(L + inViewPos); - float diffuse = max(dot(N, L), ambient); - vec3 lightColor = vec3(1.0); - outFragColor.rgb = max(lightColor * (diffuse * color.rgb), vec3(0.0)); - outFragColor.rgb *= shadow; - outFragColor.a = color.a; - - // Color cascades (if enabled) - if (ubo.colorCascades == 1) { - switch(cascadeIndex) { - case 0 : - outFragColor.rgb *= vec3(1.0f, 0.25f, 0.25f); - break; - case 1 : - outFragColor.rgb *= vec3(0.25f, 1.0f, 0.25f); - break; - case 2 : - outFragColor.rgb *= vec3(0.25f, 0.25f, 1.0f); - break; - case 3 : - outFragColor.rgb *= vec3(1.0f, 1.0f, 0.25f); - break; - } - } -} diff --git a/shaders/glsl/shadowmappingcascade/scene.frag.spv b/shaders/glsl/shadowmappingcascade/scene.frag.spv deleted file mode 100644 index 86a6d312..00000000 Binary files a/shaders/glsl/shadowmappingcascade/scene.frag.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingcascade/scene.vert b/shaders/glsl/shadowmappingcascade/scene.vert deleted file mode 100644 index 4d0649f7..00000000 --- a/shaders/glsl/shadowmappingcascade/scene.vert +++ /dev/null @@ -1,35 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inNormal; - -layout (binding = 0) uniform UBO { - mat4 projection; - mat4 view; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewPos; -layout (location = 3) out vec3 outPos; -layout (location = 4) out vec2 outUV; - -layout(push_constant) uniform PushConsts { - vec4 position; - uint cascadeIndex; -} pushConsts; - -void main() -{ - outColor = inColor; - outNormal = inNormal; - outUV = inUV; - vec3 pos = inPos + pushConsts.position.xyz; - outPos = pos; - outViewPos = (ubo.view * vec4(pos.xyz, 1.0)).xyz; - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(pos.xyz, 1.0); -} - diff --git a/shaders/glsl/shadowmappingcascade/scene.vert.spv b/shaders/glsl/shadowmappingcascade/scene.vert.spv deleted file mode 100644 index e085b16a..00000000 Binary files a/shaders/glsl/shadowmappingcascade/scene.vert.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingomni/cubemapdisplay.frag b/shaders/glsl/shadowmappingomni/cubemapdisplay.frag deleted file mode 100644 index b9dfc367..00000000 --- a/shaders/glsl/shadowmappingomni/cubemapdisplay.frag +++ /dev/null @@ -1,54 +0,0 @@ -#version 450 - -layout (binding = 1) uniform samplerCube shadowCubeMap; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor.rgb = vec3(0.05); - - vec3 samplePos = vec3(0.0f); - - // Crude statement to visualize different cube map faces based on UV coordinates - int x = int(floor(inUV.x / 0.25f)); - int y = int(floor(inUV.y / (1.0 / 3.0))); - if (y == 1) { - vec2 uv = vec2(inUV.x * 4.0f, (inUV.y - 1.0/3.0) * 3.0); - uv = 2.0 * vec2(uv.x - float(x) * 1.0, uv.y) - 1.0; - switch (x) { - case 0: // NEGATIVE_X - samplePos = vec3(-1.0f, uv.y, uv.x); - break; - case 1: // POSITIVE_Z - samplePos = vec3(uv.x, uv.y, 1.0f); - break; - case 2: // POSITIVE_X - samplePos = vec3(1.0, uv.y, -uv.x); - break; - case 3: // NEGATIVE_Z - samplePos = vec3(-uv.x, uv.y, -1.0f); - break; - } - } else { - if (x == 1) { - vec2 uv = vec2((inUV.x - 0.25) * 4.0, (inUV.y - float(y) / 3.0) * 3.0); - uv = 2.0 * uv - 1.0; - switch (y) { - case 0: // NEGATIVE_Y - samplePos = vec3(uv.x, -1.0f, uv.y); - break; - case 2: // POSITIVE_Y - samplePos = vec3(uv.x, 1.0f, -uv.y); - break; - } - } - } - - if ((samplePos.x != 0.0f) && (samplePos.y != 0.0f)) { - float dist = length(texture(shadowCubeMap, samplePos).xyz) * 0.005; - outFragColor = vec4(vec3(dist), 1.0); - } -} \ No newline at end of file diff --git a/shaders/glsl/shadowmappingomni/cubemapdisplay.frag.spv b/shaders/glsl/shadowmappingomni/cubemapdisplay.frag.spv deleted file mode 100644 index bb72c916..00000000 Binary files a/shaders/glsl/shadowmappingomni/cubemapdisplay.frag.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingomni/cubemapdisplay.vert b/shaders/glsl/shadowmappingomni/cubemapdisplay.vert deleted file mode 100644 index 1c39776d..00000000 --- a/shaders/glsl/shadowmappingomni/cubemapdisplay.vert +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; -} ubo; - -layout (location = 0) out vec2 outUV; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV.xy * 2.0f - 1.0f, 0.0f, 1.0f); -} - diff --git a/shaders/glsl/shadowmappingomni/cubemapdisplay.vert.spv b/shaders/glsl/shadowmappingomni/cubemapdisplay.vert.spv deleted file mode 100644 index 6d7ed100..00000000 Binary files a/shaders/glsl/shadowmappingomni/cubemapdisplay.vert.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingomni/offscreen.frag b/shaders/glsl/shadowmappingomni/offscreen.frag deleted file mode 100644 index cccc4f08..00000000 --- a/shaders/glsl/shadowmappingomni/offscreen.frag +++ /dev/null @@ -1,13 +0,0 @@ -#version 450 - -layout (location = 0) out float outFragColor; - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec3 inLightPos; - -void main() -{ - // Store distance to light as 32 bit float value - vec3 lightVec = inPos.xyz - inLightPos; - outFragColor = length(lightVec); -} \ No newline at end of file diff --git a/shaders/glsl/shadowmappingomni/offscreen.frag.spv b/shaders/glsl/shadowmappingomni/offscreen.frag.spv deleted file mode 100644 index 56001294..00000000 Binary files a/shaders/glsl/shadowmappingomni/offscreen.frag.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingomni/offscreen.vert b/shaders/glsl/shadowmappingomni/offscreen.vert deleted file mode 100644 index e0c30d81..00000000 --- a/shaders/glsl/shadowmappingomni/offscreen.vert +++ /dev/null @@ -1,32 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout (location = 0) out vec4 outPos; -layout (location = 1) out vec3 outLightPos; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 lightPos; -} ubo; - -layout(push_constant) uniform PushConsts -{ - mat4 view; -} pushConsts; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - gl_Position = ubo.projection * pushConsts.view * ubo.model * vec4(inPos, 1.0); - - outPos = vec4(inPos, 1.0); - outLightPos = ubo.lightPos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/shadowmappingomni/offscreen.vert.spv b/shaders/glsl/shadowmappingomni/offscreen.vert.spv deleted file mode 100644 index 6ec7eaf1..00000000 Binary files a/shaders/glsl/shadowmappingomni/offscreen.vert.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingomni/scene.frag b/shaders/glsl/shadowmappingomni/scene.frag deleted file mode 100644 index 88b9c8ec..00000000 --- a/shaders/glsl/shadowmappingomni/scene.frag +++ /dev/null @@ -1,40 +0,0 @@ -#version 450 - -layout (binding = 1) uniform samplerCube shadowCubeMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inEyePos; -layout (location = 3) in vec3 inLightVec; -layout (location = 4) in vec3 inWorldPos; -layout (location = 5) in vec3 inLightPos; - -layout (location = 0) out vec4 outFragColor; - -#define EPSILON 0.15 -#define SHADOW_OPACITY 0.5 - -void main() -{ - // Lighting - vec3 N = normalize(inNormal); - vec3 L = normalize(vec3(1.0)); - - vec3 Eye = normalize(-inEyePos); - vec3 Reflected = normalize(reflect(-inLightVec, inNormal)); - - vec4 IAmbient = vec4(vec3(0.05), 1.0); - vec4 IDiffuse = vec4(1.0) * max(dot(inNormal, inLightVec), 0.0); - - outFragColor = vec4(IAmbient + IDiffuse * vec4(inColor, 1.0)); - - // Shadow - vec3 lightVec = inWorldPos - inLightPos; - float sampledDist = texture(shadowCubeMap, lightVec).r; - float dist = length(lightVec); - - // Check if fragment is in shadow - float shadow = (dist <= sampledDist + EPSILON) ? 1.0 : SHADOW_OPACITY; - - outFragColor.rgb *= shadow; -} \ No newline at end of file diff --git a/shaders/glsl/shadowmappingomni/scene.frag.spv b/shaders/glsl/shadowmappingomni/scene.frag.spv deleted file mode 100644 index 2043a2c2..00000000 Binary files a/shaders/glsl/shadowmappingomni/scene.frag.spv and /dev/null differ diff --git a/shaders/glsl/shadowmappingomni/scene.vert b/shaders/glsl/shadowmappingomni/scene.vert deleted file mode 100644 index aebcaa11..00000000 --- a/shaders/glsl/shadowmappingomni/scene.vert +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outEyePos; -layout (location = 3) out vec3 outLightVec; -layout (location = 4) out vec3 outWorldPos; -layout (location = 5) out vec3 outLightPos; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outColor = inColor; - outNormal = inNormal; - - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); - outEyePos = vec3(ubo.model * vec4(inPos, 1.0f)); - outLightVec = normalize(ubo.lightPos.xyz - inPos.xyz); - outWorldPos = inPos; - - outLightPos = ubo.lightPos.xyz; -} - diff --git a/shaders/glsl/shadowmappingomni/scene.vert.spv b/shaders/glsl/shadowmappingomni/scene.vert.spv deleted file mode 100644 index add79db3..00000000 Binary files a/shaders/glsl/shadowmappingomni/scene.vert.spv and /dev/null differ diff --git a/shaders/glsl/specializationconstants/uber.frag b/shaders/glsl/specializationconstants/uber.frag deleted file mode 100644 index fa150708..00000000 --- a/shaders/glsl/specializationconstants/uber.frag +++ /dev/null @@ -1,71 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColormap; -layout (binding = 2) uniform sampler2D samplerDiscard; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -// We use this constant to control the flow of the shader depending on the -// lighting model selected at pipeline creation time -layout (constant_id = 0) const int LIGHTING_MODEL = 0; -// Parameter for the toon shading part of the shader -layout (constant_id = 1) const float PARAM_TOON_DESATURATION = 0.0f; - -void main() -{ - switch (LIGHTING_MODEL) { - case 0: // Phong - { - vec3 ambient = inColor * vec3(0.25); - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * inColor; - vec3 specular = pow(max(dot(R, V), 0.0), 32.0) * vec3(0.75); - outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0); - break; - } - case 1: // Toon - { - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - float intensity = dot(N,L); - vec3 color; - if (intensity > 0.98) - color = inColor * 1.5; - else if (intensity > 0.9) - color = inColor * 1.0; - else if (intensity > 0.5) - color = inColor * 0.6; - else if (intensity > 0.25) - color = inColor * 0.4; - else - color = inColor * 0.2; - // Desaturate a bit - color = vec3(mix(color, vec3(dot(vec3(0.2126,0.7152,0.0722), color)), PARAM_TOON_DESATURATION)); - outFragColor.rgb = color; - break; - } - case 2: // Textured - { - vec4 color = texture(samplerColormap, inUV).rrra; - vec3 ambient = color.rgb * vec3(0.25) * inColor; - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * color.rgb; - float specular = pow(max(dot(R, V), 0.0), 32.0) * color.a; - outFragColor = vec4(ambient + diffuse + vec3(specular), 1.0); - break; - } - } -} \ No newline at end of file diff --git a/shaders/glsl/specializationconstants/uber.frag.spv b/shaders/glsl/specializationconstants/uber.frag.spv deleted file mode 100644 index d84677c7..00000000 Binary files a/shaders/glsl/specializationconstants/uber.frag.spv and /dev/null differ diff --git a/shaders/glsl/specializationconstants/uber.vert b/shaders/glsl/specializationconstants/uber.vert deleted file mode 100644 index d9139507..00000000 --- a/shaders/glsl/specializationconstants/uber.vert +++ /dev/null @@ -1,38 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec2 outUV; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - outUV = inUV; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(ubo.model) * inNormal; - vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/specializationconstants/uber.vert.spv b/shaders/glsl/specializationconstants/uber.vert.spv deleted file mode 100644 index 82758e68..00000000 Binary files a/shaders/glsl/specializationconstants/uber.vert.spv and /dev/null differ diff --git a/shaders/glsl/sphericalenvmapping/sem.frag b/shaders/glsl/sphericalenvmapping/sem.frag deleted file mode 100644 index b233bf37..00000000 --- a/shaders/glsl/sphericalenvmapping/sem.frag +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2DArray matCap; - -layout (location = 0) in vec3 inColor; -layout (location = 1) in vec3 inEyePos; -layout (location = 2) in vec3 inNormal; -layout (location = 3) in flat int inTexIndex; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 r = reflect( inEyePos, inNormal ); - vec3 r2 = vec3( r.x, r.y, r.z + 1.0 ); - float m = 2.0 * length( r2 ); - vec2 vN = r.xy / m + .5; - outFragColor = vec4( texture( matCap, vec3(vN, inTexIndex)).rgb * (clamp(inColor.r * 2, 0.0, 1.0)), 1.0 ); -} diff --git a/shaders/glsl/sphericalenvmapping/sem.frag.spv b/shaders/glsl/sphericalenvmapping/sem.frag.spv deleted file mode 100644 index 3c721b2b..00000000 Binary files a/shaders/glsl/sphericalenvmapping/sem.frag.spv and /dev/null differ diff --git a/shaders/glsl/sphericalenvmapping/sem.vert b/shaders/glsl/sphericalenvmapping/sem.vert deleted file mode 100644 index 1de7a3d5..00000000 --- a/shaders/glsl/sphericalenvmapping/sem.vert +++ /dev/null @@ -1,31 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 normal; - mat4 view; - int texIndex; -} ubo; - -layout (location = 0) out vec3 outColor; -layout (location = 1) out vec3 outEyePos; -layout (location = 2) out vec3 outNormal; -layout (location = 3) out flat int outTexIndex; - -void main() -{ - outColor = inColor; - mat4 modelView = ubo.view * ubo.model; - outEyePos = normalize( vec3( modelView * inPos ) ); - outTexIndex = ubo.texIndex; - outNormal = normalize( mat3(ubo.normal) * inNormal ); - vec3 r = reflect( outEyePos, outNormal ); - float m = 2.0 * sqrt( pow(r.x, 2.0) + pow(r.y, 2.0) + pow(r.z + 1.0, 2.0)); - gl_Position = ubo.projection * modelView * inPos; -} diff --git a/shaders/glsl/sphericalenvmapping/sem.vert.spv b/shaders/glsl/sphericalenvmapping/sem.vert.spv deleted file mode 100644 index da074648..00000000 Binary files a/shaders/glsl/sphericalenvmapping/sem.vert.spv and /dev/null differ diff --git a/shaders/glsl/ssao/blur.frag b/shaders/glsl/ssao/blur.frag deleted file mode 100644 index f26c8453..00000000 --- a/shaders/glsl/ssao/blur.frag +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 - -layout (binding = 0) uniform sampler2D samplerSSAO; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out float outFragColor; - -void main() -{ - const int blurRange = 2; - int n = 0; - vec2 texelSize = 1.0 / vec2(textureSize(samplerSSAO, 0)); - float result = 0.0; - for (int x = -blurRange; x <= blurRange; x++) - { - for (int y = -blurRange; y <= blurRange; y++) - { - vec2 offset = vec2(float(x), float(y)) * texelSize; - result += texture(samplerSSAO, inUV + offset).r; - n++; - } - } - outFragColor = result / (float(n)); -} \ No newline at end of file diff --git a/shaders/glsl/ssao/blur.frag.spv b/shaders/glsl/ssao/blur.frag.spv deleted file mode 100644 index 4556dfac..00000000 Binary files a/shaders/glsl/ssao/blur.frag.spv and /dev/null differ diff --git a/shaders/glsl/ssao/composition.frag b/shaders/glsl/ssao/composition.frag deleted file mode 100644 index b90ba57a..00000000 --- a/shaders/glsl/ssao/composition.frag +++ /dev/null @@ -1,52 +0,0 @@ -#version 450 - -layout (binding = 0) uniform sampler2D samplerposition; -layout (binding = 1) uniform sampler2D samplerNormal; -layout (binding = 2) uniform sampler2D samplerAlbedo; -layout (binding = 3) uniform sampler2D samplerSSAO; -layout (binding = 4) uniform sampler2D samplerSSAOBlur; -layout (binding = 5) uniform UBO -{ - mat4 _dummy; - int ssao; - int ssaoOnly; - int ssaoBlur; -} uboParams; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 fragPos = texture(samplerposition, inUV).rgb; - vec3 normal = normalize(texture(samplerNormal, inUV).rgb * 2.0 - 1.0); - vec4 albedo = texture(samplerAlbedo, inUV); - - float ssao = (uboParams.ssaoBlur == 1) ? texture(samplerSSAOBlur, inUV).r : texture(samplerSSAO, inUV).r; - - vec3 lightPos = vec3(0.0); - vec3 L = normalize(lightPos - fragPos); - float NdotL = max(0.5, dot(normal, L)); - - if (uboParams.ssaoOnly == 1) - { - outFragColor.rgb = ssao.rrr; - } - else - { - vec3 baseColor = albedo.rgb * NdotL; - - if (uboParams.ssao == 1) - { - outFragColor.rgb = ssao.rrr; - - if (uboParams.ssaoOnly != 1) - outFragColor.rgb *= baseColor; - } - else - { - outFragColor.rgb = baseColor; - } - } -} \ No newline at end of file diff --git a/shaders/glsl/ssao/composition.frag.spv b/shaders/glsl/ssao/composition.frag.spv deleted file mode 100644 index b4b65b09..00000000 Binary files a/shaders/glsl/ssao/composition.frag.spv and /dev/null differ diff --git a/shaders/glsl/ssao/fullscreen.vert b/shaders/glsl/ssao/fullscreen.vert deleted file mode 100644 index a5d60d0e..00000000 --- a/shaders/glsl/ssao/fullscreen.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} diff --git a/shaders/glsl/ssao/fullscreen.vert.spv b/shaders/glsl/ssao/fullscreen.vert.spv deleted file mode 100644 index 4040f608..00000000 Binary files a/shaders/glsl/ssao/fullscreen.vert.spv and /dev/null differ diff --git a/shaders/glsl/ssao/gbuffer.frag b/shaders/glsl/ssao/gbuffer.frag deleted file mode 100644 index ec7f3682..00000000 --- a/shaders/glsl/ssao/gbuffer.frag +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inPos; - -layout (location = 0) out vec4 outPosition; -layout (location = 1) out vec4 outNormal; -layout (location = 2) out vec4 outAlbedo; - -layout (set = 0, binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - float nearPlane; - float farPlane; -} ubo; - -layout (set = 1, binding = 0) uniform sampler2D samplerColormap; - -float linearDepth(float depth) -{ - float z = depth * 2.0f - 1.0f; - return (2.0f * ubo.nearPlane * ubo.farPlane) / (ubo.farPlane + ubo.nearPlane - z * (ubo.farPlane - ubo.nearPlane)); -} - -void main() -{ - outPosition = vec4(inPos, linearDepth(gl_FragCoord.z)); - outNormal = vec4(normalize(inNormal) * 0.5 + 0.5, 1.0); - outAlbedo = texture(samplerColormap, inUV) * vec4(inColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/ssao/gbuffer.frag.spv b/shaders/glsl/ssao/gbuffer.frag.spv deleted file mode 100644 index 40d1af46..00000000 Binary files a/shaders/glsl/ssao/gbuffer.frag.spv and /dev/null differ diff --git a/shaders/glsl/ssao/gbuffer.vert b/shaders/glsl/ssao/gbuffer.vert deleted file mode 100644 index e5257322..00000000 --- a/shaders/glsl/ssao/gbuffer.vert +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; -layout (location = 2) out vec3 outColor; -layout (location = 3) out vec3 outPos; - -void main() -{ - gl_Position = ubo.projection * ubo.view * ubo.model * inPos; - - outUV = inUV; - - // Vertex position in view space - outPos = vec3(ubo.view * ubo.model * inPos); - - // Normal in view space - mat3 normalMatrix = transpose(inverse(mat3(ubo.view * ubo.model))); - outNormal = normalMatrix * inNormal; - - outColor = inColor; -} diff --git a/shaders/glsl/ssao/gbuffer.vert.spv b/shaders/glsl/ssao/gbuffer.vert.spv deleted file mode 100644 index 1d564e07..00000000 Binary files a/shaders/glsl/ssao/gbuffer.vert.spv and /dev/null differ diff --git a/shaders/glsl/ssao/ssao.frag b/shaders/glsl/ssao/ssao.frag deleted file mode 100644 index 88aac7e7..00000000 --- a/shaders/glsl/ssao/ssao.frag +++ /dev/null @@ -1,65 +0,0 @@ -#version 450 - -layout (binding = 0) uniform sampler2D samplerPositionDepth; -layout (binding = 1) uniform sampler2D samplerNormal; -layout (binding = 2) uniform sampler2D ssaoNoise; - -layout (constant_id = 0) const int SSAO_KERNEL_SIZE = 64; -layout (constant_id = 1) const float SSAO_RADIUS = 0.5; - -layout (binding = 3) uniform UBOSSAOKernel -{ - vec4 samples[SSAO_KERNEL_SIZE]; -} uboSSAOKernel; - -layout (binding = 4) uniform UBO -{ - mat4 projection; -} ubo; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out float outFragColor; - -void main() -{ - // Get G-Buffer values - vec3 fragPos = texture(samplerPositionDepth, inUV).rgb; - vec3 normal = normalize(texture(samplerNormal, inUV).rgb * 2.0 - 1.0); - - // Get a random vector using a noise lookup - ivec2 texDim = textureSize(samplerPositionDepth, 0); - ivec2 noiseDim = textureSize(ssaoNoise, 0); - const vec2 noiseUV = vec2(float(texDim.x)/float(noiseDim.x), float(texDim.y)/(noiseDim.y)) * inUV; - vec3 randomVec = texture(ssaoNoise, noiseUV).xyz * 2.0 - 1.0; - - // Create TBN matrix - vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); - vec3 bitangent = cross(tangent, normal); - mat3 TBN = mat3(tangent, bitangent, normal); - - // Calculate occlusion value - float occlusion = 0.0f; - // remove banding - const float bias = 0.025f; - for(int i = 0; i < SSAO_KERNEL_SIZE; i++) - { - vec3 samplePos = TBN * uboSSAOKernel.samples[i].xyz; - samplePos = fragPos + samplePos * SSAO_RADIUS; - - // project - vec4 offset = vec4(samplePos, 1.0f); - offset = ubo.projection * offset; - offset.xyz /= offset.w; - offset.xyz = offset.xyz * 0.5f + 0.5f; - - float sampleDepth = -texture(samplerPositionDepth, offset.xy).w; - - float rangeCheck = smoothstep(0.0f, 1.0f, SSAO_RADIUS / abs(fragPos.z - sampleDepth)); - occlusion += (sampleDepth >= samplePos.z + bias ? 1.0f : 0.0f) * rangeCheck; - } - occlusion = 1.0 - (occlusion / float(SSAO_KERNEL_SIZE)); - - outFragColor = occlusion; -} - diff --git a/shaders/glsl/ssao/ssao.frag.spv b/shaders/glsl/ssao/ssao.frag.spv deleted file mode 100644 index fd243391..00000000 Binary files a/shaders/glsl/ssao/ssao.frag.spv and /dev/null differ diff --git a/shaders/glsl/stencilbuffer/outline.frag b/shaders/glsl/stencilbuffer/outline.frag deleted file mode 100644 index eeb56cc3..00000000 --- a/shaders/glsl/stencilbuffer/outline.frag +++ /dev/null @@ -1,8 +0,0 @@ -#version 450 - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = vec4(vec3(1.0), 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/stencilbuffer/outline.frag.spv b/shaders/glsl/stencilbuffer/outline.frag.spv deleted file mode 100644 index 368f53e2..00000000 Binary files a/shaders/glsl/stencilbuffer/outline.frag.spv and /dev/null differ diff --git a/shaders/glsl/stencilbuffer/outline.vert b/shaders/glsl/stencilbuffer/outline.vert deleted file mode 100644 index ea6fc171..00000000 --- a/shaders/glsl/stencilbuffer/outline.vert +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 2) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 lightPos; - float outlineWidth; -} ubo; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - // Extrude along normal - vec4 pos = vec4(inPos.xyz + inNormal * ubo.outlineWidth, inPos.w); - gl_Position = ubo.projection * ubo.model * pos; -} diff --git a/shaders/glsl/stencilbuffer/outline.vert.spv b/shaders/glsl/stencilbuffer/outline.vert.spv deleted file mode 100644 index ea2fcb85..00000000 Binary files a/shaders/glsl/stencilbuffer/outline.vert.spv and /dev/null differ diff --git a/shaders/glsl/stencilbuffer/toon.frag b/shaders/glsl/stencilbuffer/toon.frag deleted file mode 100644 index 3d6a081a..00000000 --- a/shaders/glsl/stencilbuffer/toon.frag +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 color; - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - float intensity = dot(N,L); - if (intensity > 0.98) - color = inColor * 1.5; - else if (intensity > 0.9) - color = inColor * 1.0; - else if (intensity > 0.5) - color = inColor * 0.6; - else if (intensity > 0.25) - color = inColor * 0.4; - else - color = inColor * 0.2; - // Desaturate a bit - color = vec3(mix(color, vec3(dot(vec3(0.2126,0.7152,0.0722), color)), 0.1)); - outFragColor.rgb = color; -} \ No newline at end of file diff --git a/shaders/glsl/stencilbuffer/toon.frag.spv b/shaders/glsl/stencilbuffer/toon.frag.spv deleted file mode 100644 index 79117e4b..00000000 Binary files a/shaders/glsl/stencilbuffer/toon.frag.spv and /dev/null differ diff --git a/shaders/glsl/stencilbuffer/toon.vert b/shaders/glsl/stencilbuffer/toon.vert deleted file mode 100644 index a6c00d95..00000000 --- a/shaders/glsl/stencilbuffer/toon.vert +++ /dev/null @@ -1,31 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outColor = vec3(1.0, 0.0, 0.0); - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - outNormal = mat3(ubo.model) * inNormal; - vec4 pos = ubo.model * vec4(inPos, 1.0); - vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/stencilbuffer/toon.vert.spv b/shaders/glsl/stencilbuffer/toon.vert.spv deleted file mode 100644 index 9831ce38..00000000 Binary files a/shaders/glsl/stencilbuffer/toon.vert.spv and /dev/null differ diff --git a/shaders/glsl/subpasses/composition.frag b/shaders/glsl/subpasses/composition.frag deleted file mode 100644 index 0134c2a2..00000000 --- a/shaders/glsl/subpasses/composition.frag +++ /dev/null @@ -1,50 +0,0 @@ -#version 450 - -layout (input_attachment_index = 0, binding = 0) uniform subpassInput inputPosition; -layout (input_attachment_index = 1, binding = 1) uniform subpassInput inputNormal; -layout (input_attachment_index = 2, binding = 2) uniform subpassInput inputAlbedo; - -layout (location = 0) in vec2 inUV; - -layout (location = 0) out vec4 outColor; - -struct Light { - vec4 position; - vec3 color; - float radius; -}; - -layout (std140, binding = 3) buffer LightsBuffer -{ - Light lights[]; -}; - -void main() -{ - // Read G-Buffer values from previous sub pass - vec3 fragPos = subpassLoad(inputPosition).rgb; - vec3 normal = subpassLoad(inputNormal).rgb; - vec4 albedo = subpassLoad(inputAlbedo); - - #define ambient 0.05 - - // Ambient part - vec3 fragcolor = albedo.rgb * ambient; - - for(int i = 0; i < lights.length(); ++i) - { - vec3 L = lights[i].position.xyz - fragPos; - float dist = length(L); - - L = normalize(L); - float atten = lights[i].radius / (pow(dist, 3.0) + 1.0); - - vec3 N = normalize(normal); - float NdotL = max(0.0, dot(N, L)); - vec3 diff = lights[i].color * albedo.rgb * NdotL * atten; - - fragcolor += diff; - } - - outColor = vec4(fragcolor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/subpasses/composition.frag.spv b/shaders/glsl/subpasses/composition.frag.spv deleted file mode 100644 index ceeb9732..00000000 Binary files a/shaders/glsl/subpasses/composition.frag.spv and /dev/null differ diff --git a/shaders/glsl/subpasses/composition.vert b/shaders/glsl/subpasses/composition.vert deleted file mode 100644 index 1f318185..00000000 --- a/shaders/glsl/subpasses/composition.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout (location = 0) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); - gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); -} \ No newline at end of file diff --git a/shaders/glsl/subpasses/composition.vert.spv b/shaders/glsl/subpasses/composition.vert.spv deleted file mode 100644 index 4040f608..00000000 Binary files a/shaders/glsl/subpasses/composition.vert.spv and /dev/null differ diff --git a/shaders/glsl/subpasses/gbuffer.frag b/shaders/glsl/subpasses/gbuffer.frag deleted file mode 100644 index 44d319f4..00000000 --- a/shaders/glsl/subpasses/gbuffer.frag +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inWorldPos; - -layout (location = 0) out vec4 outColor; -layout (location = 1) out vec4 outPosition; -layout (location = 2) out vec4 outNormal; -layout (location = 3) out vec4 outAlbedo; - -layout (constant_id = 0) const float NEAR_PLANE = 0.1f; -layout (constant_id = 1) const float FAR_PLANE = 256.0f; - -float linearDepth(float depth) -{ - float z = depth * 2.0f - 1.0f; - return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE)); -} - -void main() -{ - outPosition = vec4(inWorldPos, 1.0); - - vec3 N = normalize(inNormal); - N.y = -N.y; - outNormal = vec4(N, 1.0); - - outAlbedo.rgb = inColor; - - // Store linearized depth in alpha component - outPosition.a = linearDepth(gl_FragCoord.z); - - // Write color attachments to avoid undefined behaviour (validation error) - outColor = vec4(0.0); -} \ No newline at end of file diff --git a/shaders/glsl/subpasses/gbuffer.frag.spv b/shaders/glsl/subpasses/gbuffer.frag.spv deleted file mode 100644 index 5247445a..00000000 Binary files a/shaders/glsl/subpasses/gbuffer.frag.spv and /dev/null differ diff --git a/shaders/glsl/subpasses/gbuffer.vert b/shaders/glsl/subpasses/gbuffer.vert deleted file mode 100644 index fc36c231..00000000 --- a/shaders/glsl/subpasses/gbuffer.vert +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outWorldPos; -layout (location = 3) out vec3 outTangent; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - gl_Position = ubo.projection * ubo.view * ubo.model * inPos; - - // Vertex position in world space - outWorldPos = vec3(ubo.model * inPos); - // GL to Vulkan coord space - outWorldPos.y = -outWorldPos.y; - - // Normal in world space - mat3 mNormal = transpose(inverse(mat3(ubo.model))); - outNormal = mNormal * normalize(inNormal); - - // Currently just vertex color - outColor = inColor; -} diff --git a/shaders/glsl/subpasses/gbuffer.vert.spv b/shaders/glsl/subpasses/gbuffer.vert.spv deleted file mode 100644 index cf2b5b45..00000000 Binary files a/shaders/glsl/subpasses/gbuffer.vert.spv and /dev/null differ diff --git a/shaders/glsl/subpasses/transparent.frag b/shaders/glsl/subpasses/transparent.frag deleted file mode 100644 index ca860f55..00000000 --- a/shaders/glsl/subpasses/transparent.frag +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerPositionDepth; -layout (binding = 2) uniform sampler2D samplerTexture; - -layout (location = 0) in vec3 inColor; -layout (location = 1) in vec2 inUV; - -layout (location = 0) out vec4 outColor; - -layout (constant_id = 0) const float NEAR_PLANE = 0.1f; -layout (constant_id = 1) const float FAR_PLANE = 256.0f; - -float linearDepth(float depth) -{ - float z = depth * 2.0f - 1.0f; - return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE)); -} - -void main () -{ - // Sample depth from deferred depth buffer and discard if obscured - float depth = subpassLoad(samplerPositionDepth).a; - - // Save the sampled texture color before discarding. - // This is to avoid implicit derivatives in non-uniform control flow. - vec4 sampledColor = texture(samplerTexture, inUV); - if ((depth != 0.0) && (linearDepth(gl_FragCoord.z) > depth)) - { - discard; - }; - - outColor = sampledColor; -} diff --git a/shaders/glsl/subpasses/transparent.frag.spv b/shaders/glsl/subpasses/transparent.frag.spv deleted file mode 100644 index 42fd097a..00000000 Binary files a/shaders/glsl/subpasses/transparent.frag.spv and /dev/null differ diff --git a/shaders/glsl/subpasses/transparent.vert b/shaders/glsl/subpasses/transparent.vert deleted file mode 100644 index 89e0f1f0..00000000 --- a/shaders/glsl/subpasses/transparent.vert +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inNormal; -layout (location = 3) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; -} ubo; - -layout (location = 0) out vec3 outColor; -layout (location = 1) out vec2 outUV; - -void main () -{ - outColor = inColor; - outUV = inUV; - - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/subpasses/transparent.vert.spv b/shaders/glsl/subpasses/transparent.vert.spv deleted file mode 100644 index 27d94ea3..00000000 Binary files a/shaders/glsl/subpasses/transparent.vert.spv and /dev/null differ diff --git a/shaders/glsl/terraintessellation/skysphere.frag b/shaders/glsl/terraintessellation/skysphere.frag deleted file mode 100644 index d9c9f92d..00000000 --- a/shaders/glsl/terraintessellation/skysphere.frag +++ /dev/null @@ -1,13 +0,0 @@ -#version 450 core - -layout (location = 0) in vec2 inUV; - -layout (set = 0, binding = 1) uniform sampler2D samplerColorMap; - -layout (location = 0) out vec4 outFragColor; - -void main(void) -{ - vec4 color = texture(samplerColorMap, inUV); - outFragColor = vec4(color.rgb, 1.0); -} diff --git a/shaders/glsl/terraintessellation/skysphere.frag.spv b/shaders/glsl/terraintessellation/skysphere.frag.spv deleted file mode 100644 index 925b1506..00000000 Binary files a/shaders/glsl/terraintessellation/skysphere.frag.spv and /dev/null differ diff --git a/shaders/glsl/terraintessellation/skysphere.vert b/shaders/glsl/terraintessellation/skysphere.vert deleted file mode 100644 index 32b0dfd5..00000000 --- a/shaders/glsl/terraintessellation/skysphere.vert +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 core - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (location = 0) out vec2 outUV; - -layout (set = 0, binding = 0) uniform UBO -{ - mat4 mvp; -} ubo; - -void main(void) -{ - gl_Position = ubo.mvp * vec4(inPos, 1.0); - outUV = inUV; -} diff --git a/shaders/glsl/terraintessellation/skysphere.vert.spv b/shaders/glsl/terraintessellation/skysphere.vert.spv deleted file mode 100644 index 6537b6c4..00000000 Binary files a/shaders/glsl/terraintessellation/skysphere.vert.spv and /dev/null differ diff --git a/shaders/glsl/terraintessellation/terrain.frag b/shaders/glsl/terraintessellation/terrain.frag deleted file mode 100644 index 0b6bac64..00000000 --- a/shaders/glsl/terraintessellation/terrain.frag +++ /dev/null @@ -1,61 +0,0 @@ -#version 450 - -layout (set = 0, binding = 1) uniform sampler2D samplerHeight; -layout (set = 0, binding = 2) uniform sampler2DArray samplerLayers; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; -layout (location = 4) in vec3 inEyePos; -layout (location = 5) in vec3 inWorldPos; - -layout (location = 0) out vec4 outFragColor; - -vec3 sampleTerrainLayer() -{ - // Define some layer ranges for sampling depending on terrain height - vec2 layers[6]; - layers[0] = vec2(-10.0, 10.0); - layers[1] = vec2(5.0, 45.0); - layers[2] = vec2(45.0, 80.0); - layers[3] = vec2(75.0, 100.0); - layers[4] = vec2(95.0, 140.0); - layers[5] = vec2(140.0, 190.0); - - vec3 color = vec3(0.0); - - // Get height from displacement map - float height = textureLod(samplerHeight, inUV, 0.0).r * 255.0; - - for (int i = 0; i < 6; i++) - { - float range = layers[i].y - layers[i].x; - float weight = (range - abs(height - layers[i].y)) / range; - weight = max(0.0, weight); - color += weight * texture(samplerLayers, vec3(inUV * 16.0, i)).rgb; - } - - return color; -} - -float fog(float density) -{ - const float LOG2 = -1.442695; - float dist = gl_FragCoord.z / gl_FragCoord.w * 0.1; - float d = density * dist; - return 1.0 - clamp(exp2(d * d * LOG2), 0.0, 1.0); -} - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 ambient = vec3(0.5); - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - - vec4 color = vec4((ambient + diffuse) * sampleTerrainLayer(), 1.0); - - const vec4 fogColor = vec4(0.47, 0.5, 0.67, 0.0); - outFragColor = mix(color, fogColor, fog(0.25)); -} diff --git a/shaders/glsl/terraintessellation/terrain.frag.spv b/shaders/glsl/terraintessellation/terrain.frag.spv deleted file mode 100644 index 8a0d6a47..00000000 Binary files a/shaders/glsl/terraintessellation/terrain.frag.spv and /dev/null differ diff --git a/shaders/glsl/terraintessellation/terrain.tesc b/shaders/glsl/terraintessellation/terrain.tesc deleted file mode 100644 index e92dfc82..00000000 --- a/shaders/glsl/terraintessellation/terrain.tesc +++ /dev/null @@ -1,116 +0,0 @@ -#version 450 - -layout(set = 0, binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec4 lightPos; - vec4 frustumPlanes[6]; - float displacementFactor; - float tessellationFactor; - vec2 viewportDim; - float tessellatedEdgeSize; -} ubo; - -layout(set = 0, binding = 1) uniform sampler2D samplerHeight; - -layout (vertices = 4) out; - -layout (location = 0) in vec3 inNormal[]; -layout (location = 1) in vec2 inUV[]; - -layout (location = 0) out vec3 outNormal[4]; -layout (location = 1) out vec2 outUV[4]; - -// Calculate the tessellation factor based on screen space -// dimensions of the edge -float screenSpaceTessFactor(vec4 p0, vec4 p1) -{ - // Calculate edge mid point - vec4 midPoint = 0.5 * (p0 + p1); - // Sphere radius as distance between the control points - float radius = distance(p0, p1) / 2.0; - - // View space - vec4 v0 = ubo.modelview * midPoint; - - // Project into clip space - vec4 clip0 = (ubo.projection * (v0 - vec4(radius, vec3(0.0)))); - vec4 clip1 = (ubo.projection * (v0 + vec4(radius, vec3(0.0)))); - - // Get normalized device coordinates - clip0 /= clip0.w; - clip1 /= clip1.w; - - // Convert to viewport coordinates - clip0.xy *= ubo.viewportDim; - clip1.xy *= ubo.viewportDim; - - // Return the tessellation factor based on the screen size - // given by the distance of the two edge control points in screen space - // and a reference (min.) tessellation size for the edge set by the application - return clamp(distance(clip0, clip1) / ubo.tessellatedEdgeSize * ubo.tessellationFactor, 1.0, 64.0); -} - -// Checks the current's patch visibility against the frustum using a sphere check -// Sphere radius is given by the patch size -bool frustumCheck() -{ - // Fixed radius (increase if patch size is increased in example) - const float radius = 8.0f; - vec4 pos = gl_in[gl_InvocationID].gl_Position; - pos.y -= textureLod(samplerHeight, inUV[0], 0.0).r * ubo.displacementFactor; - - // Check sphere against frustum planes - for (int i = 0; i < 6; i++) { - if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0) - { - return false; - } - } - return true; -} - -void main() -{ - if (gl_InvocationID == 0) - { - if (!frustumCheck()) - { - gl_TessLevelInner[0] = 0.0; - gl_TessLevelInner[1] = 0.0; - gl_TessLevelOuter[0] = 0.0; - gl_TessLevelOuter[1] = 0.0; - gl_TessLevelOuter[2] = 0.0; - gl_TessLevelOuter[3] = 0.0; - } - else - { - if (ubo.tessellationFactor > 0.0) - { - gl_TessLevelOuter[0] = screenSpaceTessFactor(gl_in[3].gl_Position, gl_in[0].gl_Position); - gl_TessLevelOuter[1] = screenSpaceTessFactor(gl_in[0].gl_Position, gl_in[1].gl_Position); - gl_TessLevelOuter[2] = screenSpaceTessFactor(gl_in[1].gl_Position, gl_in[2].gl_Position); - gl_TessLevelOuter[3] = screenSpaceTessFactor(gl_in[2].gl_Position, gl_in[3].gl_Position); - gl_TessLevelInner[0] = mix(gl_TessLevelOuter[0], gl_TessLevelOuter[3], 0.5); - gl_TessLevelInner[1] = mix(gl_TessLevelOuter[2], gl_TessLevelOuter[1], 0.5); - } - else - { - // Tessellation factor can be set to zero by example - // to demonstrate a simple passthrough - gl_TessLevelInner[0] = 1.0; - gl_TessLevelInner[1] = 1.0; - gl_TessLevelOuter[0] = 1.0; - gl_TessLevelOuter[1] = 1.0; - gl_TessLevelOuter[2] = 1.0; - gl_TessLevelOuter[3] = 1.0; - } - } - - } - - gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; - outNormal[gl_InvocationID] = inNormal[gl_InvocationID]; - outUV[gl_InvocationID] = inUV[gl_InvocationID]; -} diff --git a/shaders/glsl/terraintessellation/terrain.tesc.spv b/shaders/glsl/terraintessellation/terrain.tesc.spv deleted file mode 100644 index cd855c46..00000000 Binary files a/shaders/glsl/terraintessellation/terrain.tesc.spv and /dev/null differ diff --git a/shaders/glsl/terraintessellation/terrain.tese b/shaders/glsl/terraintessellation/terrain.tese deleted file mode 100644 index 088fc5c3..00000000 --- a/shaders/glsl/terraintessellation/terrain.tese +++ /dev/null @@ -1,54 +0,0 @@ -#version 450 - -layout (set = 0, binding = 0) uniform UBO -{ - mat4 projection; - mat4 modelview; - vec4 lightPos; - vec4 frustumPlanes[6]; - float displacementFactor; - float tessellationFactor; - vec2 viewportDim; - float tessellatedEdgeSize; -} ubo; - -layout (set = 0, binding = 1) uniform sampler2D displacementMap; - -layout(quads, equal_spacing, cw) in; - -layout (location = 0) in vec3 inNormal[]; -layout (location = 1) in vec2 inUV[]; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; -layout (location = 4) out vec3 outEyePos; -layout (location = 5) out vec3 outWorldPos; - -void main() -{ - // Interpolate UV coordinates - vec2 uv1 = mix(inUV[0], inUV[1], gl_TessCoord.x); - vec2 uv2 = mix(inUV[3], inUV[2], gl_TessCoord.x); - outUV = mix(uv1, uv2, gl_TessCoord.y); - - vec3 n1 = mix(inNormal[0], inNormal[1], gl_TessCoord.x); - vec3 n2 = mix(inNormal[3], inNormal[2], gl_TessCoord.x); - outNormal = mix(n1, n2, gl_TessCoord.y); - - // Interpolate positions - vec4 pos1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x); - vec4 pos2 = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, gl_TessCoord.x); - vec4 pos = mix(pos1, pos2, gl_TessCoord.y); - // Displace - pos.y -= textureLod(displacementMap, outUV, 0.0).r * ubo.displacementFactor; - // Perspective projection - gl_Position = ubo.projection * ubo.modelview * pos; - - // Calculate vectors for lighting based on tessellated position - outViewVec = -pos.xyz; - outLightVec = normalize(ubo.lightPos.xyz + outViewVec); - outWorldPos = pos.xyz; - outEyePos = vec3(ubo.modelview * pos); -} \ No newline at end of file diff --git a/shaders/glsl/terraintessellation/terrain.tese.spv b/shaders/glsl/terraintessellation/terrain.tese.spv deleted file mode 100644 index cdc6193d..00000000 Binary files a/shaders/glsl/terraintessellation/terrain.tese.spv and /dev/null differ diff --git a/shaders/glsl/terraintessellation/terrain.vert b/shaders/glsl/terraintessellation/terrain.vert deleted file mode 100644 index 61ef8201..00000000 --- a/shaders/glsl/terraintessellation/terrain.vert +++ /dev/null @@ -1,15 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; - -void main(void) -{ - gl_Position = vec4(inPos.xyz, 1.0); - outUV = inUV; - outNormal = inNormal; -} \ No newline at end of file diff --git a/shaders/glsl/terraintessellation/terrain.vert.spv b/shaders/glsl/terraintessellation/terrain.vert.spv deleted file mode 100644 index ce67e25d..00000000 Binary files a/shaders/glsl/terraintessellation/terrain.vert.spv and /dev/null differ diff --git a/shaders/glsl/tessellation/base.frag b/shaders/glsl/tessellation/base.frag deleted file mode 100644 index 8e3f204c..00000000 --- a/shaders/glsl/tessellation/base.frag +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 - -layout (set = 1, binding = 0) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec2 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(vec3(-4.0, -4.0, 0.0)); - - vec4 color = texture(samplerColorMap, inUV); - - outFragColor.rgb = vec3(clamp(max(dot(N,L), 0.0), 0.2, 1.0)) * color.rgb; -} diff --git a/shaders/glsl/tessellation/base.frag.spv b/shaders/glsl/tessellation/base.frag.spv deleted file mode 100644 index 3822b613..00000000 Binary files a/shaders/glsl/tessellation/base.frag.spv and /dev/null differ diff --git a/shaders/glsl/tessellation/base.vert b/shaders/glsl/tessellation/base.vert deleted file mode 100644 index 1e5f8080..00000000 --- a/shaders/glsl/tessellation/base.vert +++ /dev/null @@ -1,15 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; - -void main(void) -{ - gl_Position = vec4(inPos.xyz, 1.0); - outNormal = inNormal; - outUV = inUV; -} \ No newline at end of file diff --git a/shaders/glsl/tessellation/base.vert.spv b/shaders/glsl/tessellation/base.vert.spv deleted file mode 100644 index 55d812e6..00000000 Binary files a/shaders/glsl/tessellation/base.vert.spv and /dev/null differ diff --git a/shaders/glsl/tessellation/passthrough.tesc b/shaders/glsl/tessellation/passthrough.tesc deleted file mode 100644 index fa74dd0a..00000000 --- a/shaders/glsl/tessellation/passthrough.tesc +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -layout (vertices = 3) out; - -layout (location = 0) in vec3 inNormal[]; -layout (location = 1) in vec2 inUV[]; - -layout (location = 0) out vec3 outNormal[3]; -layout (location = 1) out vec2 outUV[3]; - -void main(void) -{ - if (gl_InvocationID == 0) - { - gl_TessLevelInner[0] = 1.0; - gl_TessLevelOuter[0] = 1.0; - gl_TessLevelOuter[1] = 1.0; - gl_TessLevelOuter[2] = 1.0; - } - - gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; - outNormal[gl_InvocationID] = inNormal[gl_InvocationID]; - outUV[gl_InvocationID] = inUV[gl_InvocationID]; -} \ No newline at end of file diff --git a/shaders/glsl/tessellation/passthrough.tesc.spv b/shaders/glsl/tessellation/passthrough.tesc.spv deleted file mode 100644 index 51cbea34..00000000 Binary files a/shaders/glsl/tessellation/passthrough.tesc.spv and /dev/null differ diff --git a/shaders/glsl/tessellation/passthrough.tese b/shaders/glsl/tessellation/passthrough.tese deleted file mode 100644 index d8c34701..00000000 --- a/shaders/glsl/tessellation/passthrough.tese +++ /dev/null @@ -1,28 +0,0 @@ -#version 450 - -layout (triangles, fractional_odd_spacing, cw) in; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - float tessAlpha; - float tessLevel; -} ubo; - -layout (location = 0) in vec3 inNormal[]; -layout (location = 1) in vec2 inUV[]; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; - -void main(void) -{ - gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) + - (gl_TessCoord.y * gl_in[1].gl_Position) + - (gl_TessCoord.z * gl_in[2].gl_Position); - gl_Position = ubo.projection * ubo.model * gl_Position; - - outNormal = gl_TessCoord.x*inNormal[0] + gl_TessCoord.y*inNormal[1] + gl_TessCoord.z*inNormal[2]; - outUV = gl_TessCoord.x*inUV[0] + gl_TessCoord.y*inUV[1] + gl_TessCoord.z*inUV[2]; -} \ No newline at end of file diff --git a/shaders/glsl/tessellation/passthrough.tese.spv b/shaders/glsl/tessellation/passthrough.tese.spv deleted file mode 100644 index 85340e21..00000000 Binary files a/shaders/glsl/tessellation/passthrough.tese.spv and /dev/null differ diff --git a/shaders/glsl/tessellation/pntriangles.tesc b/shaders/glsl/tessellation/pntriangles.tesc deleted file mode 100644 index dc3ad84f..00000000 --- a/shaders/glsl/tessellation/pntriangles.tesc +++ /dev/null @@ -1,86 +0,0 @@ -#version 450 - -// PN patch data -struct PnPatch -{ - float b210; - float b120; - float b021; - float b012; - float b102; - float b201; - float b111; - float n110; - float n011; - float n101; -}; - -// tessellation levels -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - float tessAlpha; - float tessLevel; -} ubo; - -layout(vertices=3) out; - -layout(location = 0) in vec3 inNormal[]; -layout(location = 1) in vec2 inUV[]; - -layout(location = 0) out vec3 outNormal[3]; -layout(location = 3) out vec2 outUV[3]; -layout(location = 6) out PnPatch outPatch[3]; - -float wij(int i, int j) -{ - return dot(gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz, inNormal[i]); -} - -float vij(int i, int j) -{ - vec3 Pj_minus_Pi = gl_in[j].gl_Position.xyz - - gl_in[i].gl_Position.xyz; - vec3 Ni_plus_Nj = inNormal[i]+inNormal[j]; - return 2.0*dot(Pj_minus_Pi, Ni_plus_Nj)/dot(Pj_minus_Pi, Pj_minus_Pi); -} - -void main() -{ - // get data - gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; - outNormal[gl_InvocationID] = inNormal[gl_InvocationID]; - outUV[gl_InvocationID] = inUV[gl_InvocationID]; - - // set base - float P0 = gl_in[0].gl_Position[gl_InvocationID]; - float P1 = gl_in[1].gl_Position[gl_InvocationID]; - float P2 = gl_in[2].gl_Position[gl_InvocationID]; - float N0 = inNormal[0][gl_InvocationID]; - float N1 = inNormal[1][gl_InvocationID]; - float N2 = inNormal[2][gl_InvocationID]; - - // compute control points - outPatch[gl_InvocationID].b210 = (2.0*P0 + P1 - wij(0,1)*N0)/3.0; - outPatch[gl_InvocationID].b120 = (2.0*P1 + P0 - wij(1,0)*N1)/3.0; - outPatch[gl_InvocationID].b021 = (2.0*P1 + P2 - wij(1,2)*N1)/3.0; - outPatch[gl_InvocationID].b012 = (2.0*P2 + P1 - wij(2,1)*N2)/3.0; - outPatch[gl_InvocationID].b102 = (2.0*P2 + P0 - wij(2,0)*N2)/3.0; - outPatch[gl_InvocationID].b201 = (2.0*P0 + P2 - wij(0,2)*N0)/3.0; - float E = ( outPatch[gl_InvocationID].b210 - + outPatch[gl_InvocationID].b120 - + outPatch[gl_InvocationID].b021 - + outPatch[gl_InvocationID].b012 - + outPatch[gl_InvocationID].b102 - + outPatch[gl_InvocationID].b201 ) / 6.0; - float V = (P0 + P1 + P2)/3.0; - outPatch[gl_InvocationID].b111 = E + (E - V)*0.5; - outPatch[gl_InvocationID].n110 = N0+N1-vij(0,1)*(P1-P0); - outPatch[gl_InvocationID].n011 = N1+N2-vij(1,2)*(P2-P1); - outPatch[gl_InvocationID].n101 = N2+N0-vij(2,0)*(P0-P2); - - // set tess levels - gl_TessLevelOuter[gl_InvocationID] = ubo.tessLevel; - gl_TessLevelInner[0] = ubo.tessLevel; -} \ No newline at end of file diff --git a/shaders/glsl/tessellation/pntriangles.tesc.spv b/shaders/glsl/tessellation/pntriangles.tesc.spv deleted file mode 100644 index bb0ae747..00000000 Binary files a/shaders/glsl/tessellation/pntriangles.tesc.spv and /dev/null differ diff --git a/shaders/glsl/tessellation/pntriangles.tese b/shaders/glsl/tessellation/pntriangles.tese deleted file mode 100644 index a9a3e345..00000000 --- a/shaders/glsl/tessellation/pntriangles.tese +++ /dev/null @@ -1,89 +0,0 @@ -#version 450 - -// PN patch data -struct PnPatch -{ - float b210; - float b120; - float b021; - float b012; - float b102; - float b201; - float b111; - float n110; - float n011; - float n101; -}; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - float tessAlpha; - float tessLevel; -} ubo; - -layout(triangles, fractional_odd_spacing, cw) in; - -layout(location = 0) in vec3 iNormal[]; -layout(location = 3) in vec2 iTexCoord[]; -layout(location = 6) in PnPatch iPnPatch[]; - -layout(location = 0) out vec3 oNormal; -layout(location = 1) out vec2 oTexCoord; - -#define uvw gl_TessCoord - -void main() -{ - vec3 uvwSquared = uvw * uvw; - vec3 uvwCubed = uvwSquared * uvw; - - // extract control points - vec3 b210 = vec3(iPnPatch[0].b210, iPnPatch[1].b210, iPnPatch[2].b210); - vec3 b120 = vec3(iPnPatch[0].b120, iPnPatch[1].b120, iPnPatch[2].b120); - vec3 b021 = vec3(iPnPatch[0].b021, iPnPatch[1].b021, iPnPatch[2].b021); - vec3 b012 = vec3(iPnPatch[0].b012, iPnPatch[1].b012, iPnPatch[2].b012); - vec3 b102 = vec3(iPnPatch[0].b102, iPnPatch[1].b102, iPnPatch[2].b102); - vec3 b201 = vec3(iPnPatch[0].b201, iPnPatch[1].b201, iPnPatch[2].b201); - vec3 b111 = vec3(iPnPatch[0].b111, iPnPatch[1].b111, iPnPatch[2].b111); - - // extract control normals - vec3 n110 = normalize(vec3(iPnPatch[0].n110, iPnPatch[1].n110, iPnPatch[2].n110)); - vec3 n011 = normalize(vec3(iPnPatch[0].n011, iPnPatch[1].n011, iPnPatch[2].n011)); - vec3 n101 = normalize(vec3(iPnPatch[0].n101, iPnPatch[1].n101, iPnPatch[2].n101)); - - // compute texcoords - oTexCoord = gl_TessCoord[2]*iTexCoord[0] + gl_TessCoord[0]*iTexCoord[1] + gl_TessCoord[1]*iTexCoord[2]; - - // normal - // Barycentric normal - vec3 barNormal = gl_TessCoord[2]*iNormal[0] + gl_TessCoord[0]*iNormal[1] + gl_TessCoord[1]*iNormal[2]; - vec3 pnNormal = iNormal[0]*uvwSquared[2] + iNormal[1]*uvwSquared[0] + iNormal[2]*uvwSquared[1] - + n110*uvw[2]*uvw[0] + n011*uvw[0]*uvw[1]+ n101*uvw[2]*uvw[1]; - oNormal = ubo.tessAlpha*pnNormal + (1.0-ubo.tessAlpha) * barNormal; - - // compute interpolated pos - vec3 barPos = gl_TessCoord[2]*gl_in[0].gl_Position.xyz - + gl_TessCoord[0]*gl_in[1].gl_Position.xyz - + gl_TessCoord[1]*gl_in[2].gl_Position.xyz; - - // save some computations - uvwSquared *= 3.0; - - // compute PN position - vec3 pnPos = gl_in[0].gl_Position.xyz*uvwCubed[2] - + gl_in[1].gl_Position.xyz*uvwCubed[0] - + gl_in[2].gl_Position.xyz*uvwCubed[1] - + b210*uvwSquared[2]*uvw[0] - + b120*uvwSquared[0]*uvw[2] - + b201*uvwSquared[2]*uvw[1] - + b021*uvwSquared[0]*uvw[1] - + b102*uvwSquared[1]*uvw[2] - + b012*uvwSquared[1]*uvw[0] - + b111*6.0*uvw[0]*uvw[1]*uvw[2]; - - // final position and normal - vec3 finalPos = (1.0-ubo.tessAlpha)*barPos + ubo.tessAlpha*pnPos; - gl_Position = ubo.projection * ubo.model * vec4(finalPos,1.0); -} \ No newline at end of file diff --git a/shaders/glsl/tessellation/pntriangles.tese.spv b/shaders/glsl/tessellation/pntriangles.tese.spv deleted file mode 100644 index bb90fb34..00000000 Binary files a/shaders/glsl/tessellation/pntriangles.tese.spv and /dev/null differ diff --git a/shaders/glsl/textoverlay/mesh.frag b/shaders/glsl/textoverlay/mesh.frag deleted file mode 100644 index 3cde63d1..00000000 --- a/shaders/glsl/textoverlay/mesh.frag +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - float diffuse = max(dot(N, L), 0.0); - float specular = pow(max(dot(R, V), 0.0), 1.0); - outFragColor = vec4(vec3(diffuse + specular) * vec3(0.25), 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/textoverlay/mesh.frag.spv b/shaders/glsl/textoverlay/mesh.frag.spv deleted file mode 100644 index 1a61dc9d..00000000 Binary files a/shaders/glsl/textoverlay/mesh.frag.spv and /dev/null differ diff --git a/shaders/glsl/textoverlay/mesh.vert b/shaders/glsl/textoverlay/mesh.vert deleted file mode 100644 index 8c9e6b37..00000000 --- a/shaders/glsl/textoverlay/mesh.vert +++ /dev/null @@ -1,35 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 lightPos; -} ubo; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outNormal = inNormal; - outUV = inUV; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(transpose(inverse(ubo.model))) * normalize(inNormal); - vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/textoverlay/mesh.vert.spv b/shaders/glsl/textoverlay/mesh.vert.spv deleted file mode 100644 index 9fc041e7..00000000 Binary files a/shaders/glsl/textoverlay/mesh.vert.spv and /dev/null differ diff --git a/shaders/glsl/textoverlay/text.frag b/shaders/glsl/textoverlay/text.frag deleted file mode 100644 index 90cad461..00000000 --- a/shaders/glsl/textoverlay/text.frag +++ /dev/null @@ -1,13 +0,0 @@ -#version 450 core - -layout (location = 0) in vec2 inUV; - -layout (binding = 0) uniform sampler2D samplerFont; - -layout (location = 0) out vec4 outFragColor; - -void main(void) -{ - float color = texture(samplerFont, inUV).r; - outFragColor = vec4(color); -} diff --git a/shaders/glsl/textoverlay/text.frag.spv b/shaders/glsl/textoverlay/text.frag.spv deleted file mode 100644 index 5ee70051..00000000 Binary files a/shaders/glsl/textoverlay/text.frag.spv and /dev/null differ diff --git a/shaders/glsl/textoverlay/text.vert b/shaders/glsl/textoverlay/text.vert deleted file mode 100644 index 55b98065..00000000 --- a/shaders/glsl/textoverlay/text.vert +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 core - -layout (location = 0) in vec2 inPos; -layout (location = 1) in vec2 inUV; - -layout (location = 0) out vec2 outUV; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main(void) -{ - gl_Position = vec4(inPos, 0.0, 1.0); - outUV = inUV; -} diff --git a/shaders/glsl/textoverlay/text.vert.spv b/shaders/glsl/textoverlay/text.vert.spv deleted file mode 100644 index 07b9000a..00000000 Binary files a/shaders/glsl/textoverlay/text.vert.spv and /dev/null differ diff --git a/shaders/glsl/texture/texture.frag b/shaders/glsl/texture/texture.frag deleted file mode 100644 index 7f9b132a..00000000 --- a/shaders/glsl/texture/texture.frag +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; -layout (location = 1) in float inLodBias; -layout (location = 2) in vec3 inNormal; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec4 color = texture(samplerColor, inUV, inLodBias); - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a; - - outFragColor = vec4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/texture/texture.frag.spv b/shaders/glsl/texture/texture.frag.spv deleted file mode 100644 index 971d3e82..00000000 Binary files a/shaders/glsl/texture/texture.frag.spv and /dev/null differ diff --git a/shaders/glsl/texture/texture.vert b/shaders/glsl/texture/texture.vert deleted file mode 100644 index cfad3023..00000000 --- a/shaders/glsl/texture/texture.vert +++ /dev/null @@ -1,41 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 viewPos; - float lodBias; -} ubo; - -layout (location = 0) out vec2 outUV; -layout (location = 1) out float outLodBias; -layout (location = 2) out vec3 outNormal; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = inUV; - outLodBias = ubo.lodBias; - - vec3 worldPos = vec3(ubo.model * vec4(inPos, 1.0)); - - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(inverse(transpose(ubo.model))) * inNormal; - vec3 lightPos = vec3(0.0); - vec3 lPos = mat3(ubo.model) * lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = ubo.viewPos.xyz - pos.xyz; -} diff --git a/shaders/glsl/texture/texture.vert.spv b/shaders/glsl/texture/texture.vert.spv deleted file mode 100644 index 153cd5dd..00000000 Binary files a/shaders/glsl/texture/texture.vert.spv and /dev/null differ diff --git a/shaders/glsl/texture3d/texture3d.frag b/shaders/glsl/texture3d/texture3d.frag deleted file mode 100644 index bb0b81e1..00000000 --- a/shaders/glsl/texture3d/texture3d.frag +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler3D samplerColor; - -layout (location = 0) in vec3 inUV; -layout (location = 1) in float inLodBias; -layout (location = 2) in vec3 inNormal; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec4 color = texture(samplerColor, inUV); - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.r; - - outFragColor = vec4(diffuse * color.r + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/texture3d/texture3d.frag.spv b/shaders/glsl/texture3d/texture3d.frag.spv deleted file mode 100644 index 85811c96..00000000 Binary files a/shaders/glsl/texture3d/texture3d.frag.spv and /dev/null differ diff --git a/shaders/glsl/texture3d/texture3d.vert b/shaders/glsl/texture3d/texture3d.vert deleted file mode 100644 index 7522edc4..00000000 --- a/shaders/glsl/texture3d/texture3d.vert +++ /dev/null @@ -1,40 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 viewPos; - float depth; -} ubo; - -layout (location = 0) out vec3 outUV; -layout (location = 1) out float outLodBias; -layout (location = 2) out vec3 outNormal; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - -void main() -{ - outUV = vec3(inUV, ubo.depth); - - vec3 worldPos = vec3(ubo.model * vec4(inPos, 1.0)); - - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - vec4 pos = ubo.model * vec4(inPos, 1.0); - outNormal = mat3(inverse(transpose(ubo.model))) * inNormal; - vec3 lightPos = vec3(0.0); - vec3 lPos = mat3(ubo.model) * lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = ubo.viewPos.xyz - pos.xyz; -} diff --git a/shaders/glsl/texture3d/texture3d.vert.spv b/shaders/glsl/texture3d/texture3d.vert.spv deleted file mode 100644 index 86f3bc00..00000000 Binary files a/shaders/glsl/texture3d/texture3d.vert.spv and /dev/null differ diff --git a/shaders/glsl/texturearray/instancing.frag b/shaders/glsl/texturearray/instancing.frag deleted file mode 100644 index 75b27b1b..00000000 --- a/shaders/glsl/texturearray/instancing.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2DArray samplerArray; - -layout (location = 0) in vec3 inUV; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerArray, inUV); -} \ No newline at end of file diff --git a/shaders/glsl/texturearray/instancing.frag.spv b/shaders/glsl/texturearray/instancing.frag.spv deleted file mode 100644 index 106300c6..00000000 Binary files a/shaders/glsl/texturearray/instancing.frag.spv and /dev/null differ diff --git a/shaders/glsl/texturearray/instancing.vert b/shaders/glsl/texturearray/instancing.vert deleted file mode 100644 index cbfd27c7..00000000 --- a/shaders/glsl/texturearray/instancing.vert +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; - -struct Instance -{ - mat4 model; - float arrayIndex; -}; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - Instance instance[8]; -} ubo; - -layout (location = 0) out vec3 outUV; - -void main() -{ - outUV = vec3(inUV, ubo.instance[gl_InstanceIndex].arrayIndex); - mat4 modelView = ubo.view * ubo.instance[gl_InstanceIndex].model; - gl_Position = ubo.projection * modelView * vec4(inPos, 1.0); -} diff --git a/shaders/glsl/texturearray/instancing.vert.spv b/shaders/glsl/texturearray/instancing.vert.spv deleted file mode 100644 index 63849a67..00000000 Binary files a/shaders/glsl/texturearray/instancing.vert.spv and /dev/null differ diff --git a/shaders/glsl/texturecubemap/reflect.frag b/shaders/glsl/texturecubemap/reflect.frag deleted file mode 100644 index cab01537..00000000 --- a/shaders/glsl/texturecubemap/reflect.frag +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (binding = 1) uniform samplerCube samplerColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 invModel; - float lodBias; -} ubo; - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 cI = normalize (inPos); - vec3 cR = reflect (cI, normalize(inNormal)); - - cR = vec3(ubo.invModel * vec4(cR, 0.0)); - // Convert cubemap coordinates into Vulkan coordinate space - cR.xy *= -1.0; - - vec4 color = texture(samplerColor, cR, ubo.lodBias); - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 ambient = vec3(0.5) * color.rgb; - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.5); - outFragColor = vec4(ambient + diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/texturecubemap/reflect.frag.spv b/shaders/glsl/texturecubemap/reflect.frag.spv deleted file mode 100644 index 40f10cee..00000000 Binary files a/shaders/glsl/texturecubemap/reflect.frag.spv and /dev/null differ diff --git a/shaders/glsl/texturecubemap/reflect.vert b/shaders/glsl/texturecubemap/reflect.vert deleted file mode 100644 index fc2d84d1..00000000 --- a/shaders/glsl/texturecubemap/reflect.vert +++ /dev/null @@ -1,29 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 invModel; - float lodBias; -} ubo; - -layout (location = 0) out vec3 outPos; -layout (location = 1) out vec3 outNormal; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - outPos = vec3(ubo.model * vec4(inPos, 1.0)); - outNormal = mat3(ubo.model) * inNormal; - - vec3 lightPos = vec3(0.0f, -5.0f, 5.0f); - outLightVec = lightPos.xyz - outPos.xyz; - outViewVec = -outPos.xyz; -} diff --git a/shaders/glsl/texturecubemap/reflect.vert.spv b/shaders/glsl/texturecubemap/reflect.vert.spv deleted file mode 100644 index 1ac327aa..00000000 Binary files a/shaders/glsl/texturecubemap/reflect.vert.spv and /dev/null differ diff --git a/shaders/glsl/texturecubemap/skybox.frag b/shaders/glsl/texturecubemap/skybox.frag deleted file mode 100644 index 56b8f42c..00000000 --- a/shaders/glsl/texturecubemap/skybox.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (binding = 1) uniform samplerCube samplerCubeMap; - -layout (location = 0) in vec3 inUVW; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerCubeMap, inUVW); -} \ No newline at end of file diff --git a/shaders/glsl/texturecubemap/skybox.frag.spv b/shaders/glsl/texturecubemap/skybox.frag.spv deleted file mode 100644 index 87e4fe98..00000000 Binary files a/shaders/glsl/texturecubemap/skybox.frag.spv and /dev/null differ diff --git a/shaders/glsl/texturecubemap/skybox.vert b/shaders/glsl/texturecubemap/skybox.vert deleted file mode 100644 index 6fd365c1..00000000 --- a/shaders/glsl/texturecubemap/skybox.vert +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; -} ubo; - -layout (location = 0) out vec3 outUVW; - -void main() -{ - outUVW = inPos; - // Convert cubemap coordinates into Vulkan coordinate space - outUVW.xy *= -1.0; - // Remove translation from view matrix - mat4 viewMat = mat4(mat3(ubo.model)); - gl_Position = ubo.projection * viewMat * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/texturecubemap/skybox.vert.spv b/shaders/glsl/texturecubemap/skybox.vert.spv deleted file mode 100644 index 147cdaa2..00000000 Binary files a/shaders/glsl/texturecubemap/skybox.vert.spv and /dev/null differ diff --git a/shaders/glsl/texturecubemaparray/reflect.frag b/shaders/glsl/texturecubemaparray/reflect.frag deleted file mode 100644 index 8982b77d..00000000 --- a/shaders/glsl/texturecubemaparray/reflect.frag +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (binding = 1) uniform samplerCubeArray samplerCubeMapArray; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 invModel; - float lodBias; - int cubeMapIndex; -} ubo; - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 cI = normalize (inPos); - vec3 cR = reflect (cI, normalize(inNormal)); - - cR = vec3(ubo.invModel * vec4(cR, 0.0)); - cR.yz *= -1.0; - - vec4 color = textureLod(samplerCubeMapArray, vec4(cR, ubo.cubeMapIndex), ubo.lodBias); - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 ambient = vec3(0.5) * color.rgb; - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.5); - outFragColor = vec4(ambient + diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/texturecubemaparray/reflect.frag.spv b/shaders/glsl/texturecubemaparray/reflect.frag.spv deleted file mode 100644 index 5c3fa1be..00000000 Binary files a/shaders/glsl/texturecubemaparray/reflect.frag.spv and /dev/null differ diff --git a/shaders/glsl/texturecubemaparray/reflect.vert b/shaders/glsl/texturecubemaparray/reflect.vert deleted file mode 100644 index 135ed298..00000000 --- a/shaders/glsl/texturecubemaparray/reflect.vert +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 invModel; - float lodBias; - int cubeMapIndex; -} ubo; - -layout (location = 0) out vec3 outPos; -layout (location = 1) out vec3 outNormal; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -void main() -{ - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); - - outPos = vec3(ubo.model * vec4(inPos, 1.0)); - outNormal = mat3(ubo.model) * inNormal; - - vec3 lightPos = vec3(0.0f, -5.0f, 5.0f); - outLightVec = lightPos.xyz - outPos.xyz; - outViewVec = -outPos.xyz; -} diff --git a/shaders/glsl/texturecubemaparray/reflect.vert.spv b/shaders/glsl/texturecubemaparray/reflect.vert.spv deleted file mode 100644 index 6a75efa1..00000000 Binary files a/shaders/glsl/texturecubemaparray/reflect.vert.spv and /dev/null differ diff --git a/shaders/glsl/texturecubemaparray/skybox.frag b/shaders/glsl/texturecubemaparray/skybox.frag deleted file mode 100644 index b43bb0d2..00000000 --- a/shaders/glsl/texturecubemaparray/skybox.frag +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout (binding = 1) uniform samplerCubeArray samplerCubeMapArray; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 invModel; - float lodBias; - int cubeMapIndex; -} ubo; - -layout (location = 0) in vec3 inUVW; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = textureLod(samplerCubeMapArray, vec4(inUVW, ubo.cubeMapIndex), ubo.lodBias); -} \ No newline at end of file diff --git a/shaders/glsl/texturecubemaparray/skybox.frag.spv b/shaders/glsl/texturecubemaparray/skybox.frag.spv deleted file mode 100644 index 35ec681b..00000000 Binary files a/shaders/glsl/texturecubemaparray/skybox.frag.spv and /dev/null differ diff --git a/shaders/glsl/texturecubemaparray/skybox.vert b/shaders/glsl/texturecubemaparray/skybox.vert deleted file mode 100644 index 169086ec..00000000 --- a/shaders/glsl/texturecubemaparray/skybox.vert +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 invModel; - float lodBias; - int cubeMapIndex; -} ubo; - -layout (location = 0) out vec3 outUVW; - -void main() -{ - outUVW = inPos; - outUVW.xy *= -1.0f; - // Remove translation from view matrix - mat4 viewMat = mat4(mat3(ubo.model)); - gl_Position = ubo.projection * viewMat * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/texturecubemaparray/skybox.vert.spv b/shaders/glsl/texturecubemaparray/skybox.vert.spv deleted file mode 100644 index 7c5b09bf..00000000 Binary files a/shaders/glsl/texturecubemaparray/skybox.vert.spv and /dev/null differ diff --git a/shaders/glsl/texturemipmapgen/texture.frag b/shaders/glsl/texturemipmapgen/texture.frag deleted file mode 100644 index 613d9cdc..00000000 --- a/shaders/glsl/texturemipmapgen/texture.frag +++ /dev/null @@ -1,35 +0,0 @@ -#version 450 - -layout (set = 0, binding = 1) uniform texture2D textureColor; -layout (set = 0, binding = 2) uniform sampler samplers[3]; - -layout (location = 0) in vec2 inUV; -layout (location = 1) in float inLodBias; -layout (location = 2) in vec3 inNormal; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 viewPos; - float lodBias; - int samplerIndex; -} ubo; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec4 color = texture(sampler2D(textureColor, samplers[ubo.samplerIndex]), inUV, inLodBias); - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(L, N); - vec3 diffuse = max(dot(N, L), 0.65) * vec3(1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a; - outFragColor = vec4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/texturemipmapgen/texture.frag.spv b/shaders/glsl/texturemipmapgen/texture.frag.spv deleted file mode 100644 index 5d413988..00000000 Binary files a/shaders/glsl/texturemipmapgen/texture.frag.spv and /dev/null differ diff --git a/shaders/glsl/texturemipmapgen/texture.vert b/shaders/glsl/texturemipmapgen/texture.vert deleted file mode 100644 index 5d04b795..00000000 --- a/shaders/glsl/texturemipmapgen/texture.vert +++ /dev/null @@ -1,36 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 viewPos; - float lodBias; - int samplerIndex; -} ubo; - -layout (location = 0) out vec2 outUV; -layout (location = 1) out float outLodBias; -layout (location = 2) out vec3 outNormal; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; - -void main() -{ - outUV = inUV * vec2(2.0, 1.0); - outLodBias = ubo.lodBias; - - vec3 worldPos = vec3(ubo.model * vec4(inPos, 1.0)); - - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); - - outNormal = mat3(inverse(transpose(ubo.model))) * inNormal; - vec3 lightPos = vec3(-30.0, 0.0, 0.0); - outLightVec = worldPos - lightPos; - outViewVec = ubo.viewPos.xyz - worldPos; -} diff --git a/shaders/glsl/texturemipmapgen/texture.vert.spv b/shaders/glsl/texturemipmapgen/texture.vert.spv deleted file mode 100644 index 64ecdca3..00000000 Binary files a/shaders/glsl/texturemipmapgen/texture.vert.spv and /dev/null differ diff --git a/shaders/glsl/texturesparseresidency/sparseresidency.frag b/shaders/glsl/texturesparseresidency/sparseresidency.frag deleted file mode 100644 index a55916b8..00000000 --- a/shaders/glsl/texturesparseresidency/sparseresidency.frag +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -#extension GL_ARB_sparse_texture2 : enable -#extension GL_ARB_sparse_texture_clamp : enable - -layout (binding = 1) uniform sampler2D samplerColor; - -layout (location = 0) in vec2 inUV; -layout (location = 1) in float inLodBias; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec4 color = vec4(0.0); - - // Get residency code for current texel - int residencyCode = sparseTextureARB(samplerColor, inUV, color, inLodBias); - - // Fetch sparse until we get a valid texel - /* - float minLod = 1.0; - while (!sparseTexelsResidentARB(residencyCode)) - { - residencyCode = sparseTextureClampARB(samplerColor, inUV, minLod, color); - minLod += 1.0f; - } - */ - - // Check if texel is resident - bool texelResident = sparseTexelsResidentARB(residencyCode); - - if (!texelResident) - { - color = vec4(0.0, 0.0, 0.0, 0.0); - } - - outFragColor = color; -} \ No newline at end of file diff --git a/shaders/glsl/texturesparseresidency/sparseresidency.frag.spv b/shaders/glsl/texturesparseresidency/sparseresidency.frag.spv deleted file mode 100644 index 9f661cbe..00000000 Binary files a/shaders/glsl/texturesparseresidency/sparseresidency.frag.spv and /dev/null differ diff --git a/shaders/glsl/texturesparseresidency/sparseresidency.vert b/shaders/glsl/texturesparseresidency/sparseresidency.vert deleted file mode 100644 index e613226f..00000000 --- a/shaders/glsl/texturesparseresidency/sparseresidency.vert +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - vec4 viewPos; - float lodBias; -} ubo; - -layout (location = 0) out vec2 outUV; -layout (location = 1) out float outLodBias; - -void main() -{ - outUV = inUV; - outLodBias = ubo.lodBias; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/texturesparseresidency/sparseresidency.vert.spv b/shaders/glsl/texturesparseresidency/sparseresidency.vert.spv deleted file mode 100644 index 328462a0..00000000 Binary files a/shaders/glsl/texturesparseresidency/sparseresidency.vert.spv and /dev/null differ diff --git a/shaders/glsl/triangle/triangle.frag b/shaders/glsl/triangle/triangle.frag deleted file mode 100644 index f3e513b9..00000000 --- a/shaders/glsl/triangle/triangle.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inColor; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = vec4(inColor, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/triangle/triangle.frag.spv b/shaders/glsl/triangle/triangle.frag.spv deleted file mode 100644 index f67f2011..00000000 Binary files a/shaders/glsl/triangle/triangle.frag.spv and /dev/null differ diff --git a/shaders/glsl/triangle/triangle.vert b/shaders/glsl/triangle/triangle.vert deleted file mode 100644 index 1b14aabc..00000000 --- a/shaders/glsl/triangle/triangle.vert +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projectionMatrix; - mat4 modelMatrix; - mat4 viewMatrix; -} ubo; - -layout (location = 0) out vec3 outColor; - -out gl_PerVertex -{ - vec4 gl_Position; -}; - - -void main() -{ - outColor = inColor; - gl_Position = ubo.projectionMatrix * ubo.viewMatrix * ubo.modelMatrix * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/triangle/triangle.vert.spv b/shaders/glsl/triangle/triangle.vert.spv deleted file mode 100644 index 552792d1..00000000 Binary files a/shaders/glsl/triangle/triangle.vert.spv and /dev/null differ diff --git a/shaders/glsl/variablerateshading/scene.frag b/shaders/glsl/variablerateshading/scene.frag deleted file mode 100644 index b2b4a473..00000000 --- a/shaders/glsl/variablerateshading/scene.frag +++ /dev/null @@ -1,85 +0,0 @@ -#version 450 - -#extension GL_EXT_fragment_shading_rate : require - -layout (set = 1, binding = 0) uniform sampler2D samplerColorMap; -layout (set = 1, binding = 1) uniform sampler2D samplerNormalMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; -layout (location = 5) in vec4 inTangent; - -layout (set = 0, binding = 0) uniform UBOScene -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 lightPos; - vec4 viewPos; - int colorShadingRates; -} uboScene; - -layout (location = 0) out vec4 outFragColor; - -layout (constant_id = 0) const bool ALPHA_MASK = false; -layout (constant_id = 1) const float ALPHA_MASK_CUTOFF = 0.0f; - -void main() -{ - vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0); - - if (ALPHA_MASK) { - if (color.a < ALPHA_MASK_CUTOFF) { - discard; - } - } - - vec3 N = normalize(inNormal); - vec3 T = normalize(inTangent.xyz); - vec3 B = cross(inNormal, inTangent.xyz) * inTangent.w; - mat3 TBN = mat3(T, B, N); - N = TBN * normalize(texture(samplerNormalMap, inUV).xyz * 2.0 - vec3(1.0)); - - const float ambient = 0.25; - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), ambient).rrr; - float specular = pow(max(dot(R, V), 0.0), 32.0); - outFragColor = vec4(diffuse * color.rgb + specular, color.a); - - if (uboScene.colorShadingRates == 1) { - int v = 1; - int h = 1; - - if ((gl_ShadingRateEXT & gl_ShadingRateFlag2VerticalPixelsEXT) == gl_ShadingRateFlag2VerticalPixelsEXT) { - v = 2; - } - if ((gl_ShadingRateEXT & gl_ShadingRateFlag4VerticalPixelsEXT) == gl_ShadingRateFlag4VerticalPixelsEXT) { - v = 4; - } - if ((gl_ShadingRateEXT & gl_ShadingRateFlag2HorizontalPixelsEXT) == gl_ShadingRateFlag2HorizontalPixelsEXT) { - h = 2; - } - if ((gl_ShadingRateEXT & gl_ShadingRateFlag4HorizontalPixelsEXT) == gl_ShadingRateFlag4HorizontalPixelsEXT) { - h = 4; - } - - if (v == 1 && h == 1) { outFragColor *= vec4(0.0, 0.8, 0.4, 1.0); return; } - - if (v == 2 && h == 1) { outFragColor *= vec4(0.2, 0.6, 1.0, 1.0); return; } - - if (v == 1 && h == 2) { outFragColor *= vec4(0.0, 0.4, 0.8, 1.0); return; } - - if (v == 2 && h == 2) { outFragColor *= vec4(1.0, 1.0, 0.2, 1.0); return; } - - if (v == 4 && h == 2) { outFragColor *= vec4(0.8, 0.8, 0.0, 1.0); return; } - - if (v == 2 && h == 4) { outFragColor *= vec4(1.0, 0.4, 0.2, 1.0); return; } - - outFragColor *= vec4(0.0, 0.8, 0.4, 1.0); - } -} \ No newline at end of file diff --git a/shaders/glsl/variablerateshading/scene.frag.spv b/shaders/glsl/variablerateshading/scene.frag.spv deleted file mode 100644 index 7d356186..00000000 Binary files a/shaders/glsl/variablerateshading/scene.frag.spv and /dev/null differ diff --git a/shaders/glsl/variablerateshading/scene.vert b/shaders/glsl/variablerateshading/scene.vert deleted file mode 100644 index bf4e03ed..00000000 --- a/shaders/glsl/variablerateshading/scene.vert +++ /dev/null @@ -1,38 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inColor; -layout (location = 4) in vec4 inTangent; - -layout (set = 0, binding = 0) uniform UBOScene -{ - mat4 projection; - mat4 view; - mat4 model; - vec4 lightPos; - vec4 viewPos; - int colorShadingRates; -} uboScene; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec2 outUV; -layout (location = 3) out vec3 outViewVec; -layout (location = 4) out vec3 outLightVec; -layout (location = 5) out vec4 outTangent; - -void main() -{ - outNormal = inNormal; - outColor = inColor; - outUV = inUV; - outTangent = inTangent; - gl_Position = uboScene.projection * uboScene.view * uboScene.model * vec4(inPos.xyz, 1.0); - - outNormal = mat3(uboScene.model) * inNormal; - vec4 pos = uboScene.model * vec4(inPos, 1.0); - outLightVec = uboScene.lightPos.xyz - pos.xyz; - outViewVec = uboScene.viewPos.xyz - pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/variablerateshading/scene.vert.spv b/shaders/glsl/variablerateshading/scene.vert.spv deleted file mode 100644 index d5c2011b..00000000 Binary files a/shaders/glsl/variablerateshading/scene.vert.spv and /dev/null differ diff --git a/shaders/glsl/vertexattributes/scene.frag b/shaders/glsl/vertexattributes/scene.frag deleted file mode 100644 index c736fd31..00000000 --- a/shaders/glsl/vertexattributes/scene.frag +++ /dev/null @@ -1,43 +0,0 @@ -#version 450 - -layout (set = 1, binding = 0) uniform sampler2D samplerColorMap; -layout (set = 1, binding = 1) uniform sampler2D samplerNormalMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; -layout (location = 4) in vec4 inTangent; - -layout (location = 0) out vec4 outFragColor; - -layout(push_constant) uniform PushConsts { - mat4 model; - uint alphaMask; - float alphaMaskCuttoff; -} pushConsts; - -void main() -{ - vec4 color = texture(samplerColorMap, inUV); - - if (pushConsts.alphaMask == 1) { - if (color.a < pushConsts.alphaMaskCuttoff) { - discard; - } - } - - vec3 N = normalize(inNormal); - vec3 T = normalize(inTangent.xyz); - vec3 B = cross(inNormal, inTangent.xyz) * inTangent.w; - mat3 TBN = mat3(T, B, N); - N = TBN * normalize(texture(samplerNormalMap, inUV).xyz * 2.0 - vec3(1.0)); - - const float ambient = 0.1; - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 diffuse = max(dot(N, L), ambient).rrr; - float specular = pow(max(dot(R, V), 0.0), 32.0); - outFragColor = vec4(diffuse * color.rgb + specular, color.a); -} \ No newline at end of file diff --git a/shaders/glsl/vertexattributes/scene.frag.spv b/shaders/glsl/vertexattributes/scene.frag.spv deleted file mode 100644 index 300acdbb..00000000 Binary files a/shaders/glsl/vertexattributes/scene.frag.spv and /dev/null differ diff --git a/shaders/glsl/vertexattributes/scene.vert b/shaders/glsl/vertexattributes/scene.vert deleted file mode 100644 index 2cd8c1a6..00000000 --- a/shaders/glsl/vertexattributes/scene.vert +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec4 inTangent; - -layout (set = 0, binding = 0) uniform UBOScene -{ - mat4 projection; - mat4 view; - vec4 lightPos; - vec4 viewPos; -} uboScene; - -layout(push_constant) uniform PushConsts { - mat4 model; - uint alphaMask; - float alphaMaskCuttoff; -} pushConsts; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec2 outUV; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; -layout (location = 4) out vec4 outTangent; - -void main() -{ - outNormal = inNormal; - outUV = inUV; - outTangent = inTangent; - gl_Position = uboScene.projection * uboScene.view * pushConsts.model * vec4(inPos.xyz, 1.0); - - outNormal = mat3(pushConsts.model) * inNormal; - vec4 pos = pushConsts.model * vec4(inPos, 1.0); - outLightVec = uboScene.lightPos.xyz - pos.xyz; - outViewVec = uboScene.viewPos.xyz - pos.xyz; -} \ No newline at end of file diff --git a/shaders/glsl/vertexattributes/scene.vert.spv b/shaders/glsl/vertexattributes/scene.vert.spv deleted file mode 100644 index 83c99138..00000000 Binary files a/shaders/glsl/vertexattributes/scene.vert.spv and /dev/null differ diff --git a/shaders/glsl/viewportarray/multiview.geom b/shaders/glsl/viewportarray/multiview.geom deleted file mode 100644 index c517d069..00000000 --- a/shaders/glsl/viewportarray/multiview.geom +++ /dev/null @@ -1,45 +0,0 @@ -#version 450 - -#extension GL_ARB_viewport_array : enable - -layout (triangles, invocations = 2) in; -layout (triangle_strip, max_vertices = 3) out; - -layout (binding = 0) uniform UBO -{ - mat4 projection[2]; - mat4 modelview[2]; - vec4 lightPos; -} ubo; - -layout (location = 0) in vec3 inNormal[]; -layout (location = 1) in vec3 inColor[]; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; -layout (location = 2) out vec3 outViewVec; -layout (location = 3) out vec3 outLightVec; - -void main(void) -{ - for(int i = 0; i < gl_in.length(); i++) - { - outNormal = mat3(ubo.modelview[gl_InvocationID]) * inNormal[i]; - outColor = inColor[i]; - - vec4 pos = gl_in[i].gl_Position; - vec4 worldPos = (ubo.modelview[gl_InvocationID] * pos); - - vec3 lPos = vec3(ubo.modelview[gl_InvocationID] * ubo.lightPos); - outLightVec = lPos - worldPos.xyz; - outViewVec = -worldPos.xyz; - - gl_Position = ubo.projection[gl_InvocationID] * worldPos; - - // Set the viewport index that the vertex will be emitted to - gl_ViewportIndex = gl_InvocationID; - gl_PrimitiveID = gl_PrimitiveIDIn; - EmitVertex(); - } - EndPrimitive(); -} \ No newline at end of file diff --git a/shaders/glsl/viewportarray/multiview.geom.spv b/shaders/glsl/viewportarray/multiview.geom.spv deleted file mode 100644 index 64fb39b1..00000000 Binary files a/shaders/glsl/viewportarray/multiview.geom.spv and /dev/null differ diff --git a/shaders/glsl/viewportarray/scene.frag b/shaders/glsl/viewportarray/scene.frag deleted file mode 100644 index 94d7f9a3..00000000 --- a/shaders/glsl/viewportarray/scene.frag +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec3 inViewVec; -layout (location = 3) in vec3 inLightVec; - -layout (location = 0) out vec4 outColor; - -void main() -{ - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - vec3 ambient = vec3(0.1); - vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0); - vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); - outColor = vec4((ambient + diffuse) * inColor.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/glsl/viewportarray/scene.frag.spv b/shaders/glsl/viewportarray/scene.frag.spv deleted file mode 100644 index 1eae642c..00000000 Binary files a/shaders/glsl/viewportarray/scene.frag.spv and /dev/null differ diff --git a/shaders/glsl/viewportarray/scene.vert b/shaders/glsl/viewportarray/scene.vert deleted file mode 100644 index 5231157e..00000000 --- a/shaders/glsl/viewportarray/scene.vert +++ /dev/null @@ -1,15 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; - -layout (location = 0) out vec3 outNormal; -layout (location = 1) out vec3 outColor; - -void main() -{ - outColor = inColor; - outNormal = inNormal; - gl_Position = vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/viewportarray/scene.vert.spv b/shaders/glsl/viewportarray/scene.vert.spv deleted file mode 100644 index 379e6500..00000000 Binary files a/shaders/glsl/viewportarray/scene.vert.spv and /dev/null differ diff --git a/shaders/glsl/vulkanscene/logo.frag b/shaders/glsl/vulkanscene/logo.frag deleted file mode 100644 index 3d013b9f..00000000 --- a/shaders/glsl/vulkanscene/logo.frag +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 - -layout (location = 0) in vec2 inUV; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inEyePos; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 Eye = normalize(-inEyePos); - vec3 Reflected = normalize(reflect(-inLightVec, inNormal)); - - vec4 diff = vec4(inColor, 1.0) * max(dot(inNormal, inLightVec), 0.0); - float shininess = 0.0; - vec4 spec = vec4(1.0, 1.0, 1.0, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 2.5) * shininess; - - outFragColor = diff + spec; - outFragColor.a = 1.0; -} \ No newline at end of file diff --git a/shaders/glsl/vulkanscene/logo.frag.spv b/shaders/glsl/vulkanscene/logo.frag.spv deleted file mode 100644 index 94bf9b8e..00000000 Binary files a/shaders/glsl/vulkanscene/logo.frag.spv and /dev/null differ diff --git a/shaders/glsl/vulkanscene/logo.vert b/shaders/glsl/vulkanscene/logo.vert deleted file mode 100644 index e5c9ddf8..00000000 --- a/shaders/glsl/vulkanscene/logo.vert +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inTexCoord; -layout (location = 3) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 normal; - mat4 view; - vec3 lightpos; -} ubo; - -layout (location = 0) out vec2 outUV; -layout (location = 1) out vec3 outNormal; -layout (location = 2) out vec3 outColor; -layout (location = 3) out vec3 outEyePos; -layout (location = 4) out vec3 outLightVec; - -void main() -{ - mat4 modelView = ubo.view * ubo.model; - vec4 pos = modelView * inPos; - outUV = inTexCoord.st; - outNormal = normalize(mat3(ubo.normal) * inNormal); - outColor = inColor; - gl_Position = ubo.projection * pos; - outEyePos = vec3(modelView * pos); - vec4 lightPos = vec4(1.0, 2.0, 0.0, 1.0) * modelView; - outLightVec = normalize(lightPos.xyz - outEyePos); -} diff --git a/shaders/glsl/vulkanscene/logo.vert.spv b/shaders/glsl/vulkanscene/logo.vert.spv deleted file mode 100644 index e6183abf..00000000 Binary files a/shaders/glsl/vulkanscene/logo.vert.spv and /dev/null differ diff --git a/shaders/glsl/vulkanscene/mesh.frag b/shaders/glsl/vulkanscene/mesh.frag deleted file mode 100644 index b418a033..00000000 --- a/shaders/glsl/vulkanscene/mesh.frag +++ /dev/null @@ -1,44 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D tex; - -layout (location = 0) in vec2 inUV; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec3 inColor; -layout (location = 3) in vec3 inEyePos; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -float specpart(vec3 L, vec3 N, vec3 H) -{ - if (dot(N, L) > 0.0) - { - return pow(clamp(dot(H, N), 0.0, 1.0), 64.0); - } - return 0.0; -} - -void main() -{ - vec3 Eye = normalize(-inEyePos); - vec3 Reflected = normalize(reflect(-inLightVec, inNormal)); - - vec3 halfVec = normalize(inLightVec + inEyePos); - float diff = clamp(dot(inLightVec, inNormal), 0.0, 1.0); - float spec = specpart(inLightVec, inNormal, halfVec); - float intensity = 0.1 + diff + spec; - - vec4 IAmbient = vec4(0.2, 0.2, 0.2, 1.0); - vec4 IDiffuse = vec4(0.5, 0.5, 0.5, 0.5) * max(dot(inNormal, inLightVec), 0.0); - float shininess = 0.75; - vec4 ISpecular = vec4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 2.0) * shininess; - - outFragColor = vec4((IAmbient + IDiffuse) * vec4(inColor, 1.0) + ISpecular); - - // Some manual saturation - if (intensity > 0.95) - outFragColor *= 2.25; - if (intensity < 0.15) - outFragColor = vec4(0.1); -} \ No newline at end of file diff --git a/shaders/glsl/vulkanscene/mesh.frag.spv b/shaders/glsl/vulkanscene/mesh.frag.spv deleted file mode 100644 index 7ed6d804..00000000 Binary files a/shaders/glsl/vulkanscene/mesh.frag.spv and /dev/null differ diff --git a/shaders/glsl/vulkanscene/mesh.vert b/shaders/glsl/vulkanscene/mesh.vert deleted file mode 100644 index 80bdf299..00000000 --- a/shaders/glsl/vulkanscene/mesh.vert +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 - -layout (location = 0) in vec4 inPos; -layout (location = 1) in vec3 inNormal; -layout (location = 2) in vec2 inTexCoord; -layout (location = 3) in vec3 inColor; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 normal; - mat4 view; - vec3 lightpos; -} ubo; - -layout (location = 0) out vec2 outUV; -layout (location = 1) out vec3 outNormal; -layout (location = 2) out vec3 outColor; -layout (location = 3) out vec3 outEyePos; -layout (location = 4) out vec3 outLightVec; - -void main() -{ - outUV = inTexCoord.st; - outNormal = normalize(mat3(ubo.normal) * inNormal); - outColor = inColor; - mat4 modelView = ubo.view * ubo.model; - vec4 pos = modelView * inPos; - gl_Position = ubo.projection * pos; - outEyePos = vec3(modelView * pos); - vec4 lightPos = vec4(ubo.lightpos, 1.0) * modelView; - outLightVec = normalize(lightPos.xyz - outEyePos); -} diff --git a/shaders/glsl/vulkanscene/mesh.vert.spv b/shaders/glsl/vulkanscene/mesh.vert.spv deleted file mode 100644 index 34457bcf..00000000 Binary files a/shaders/glsl/vulkanscene/mesh.vert.spv and /dev/null differ diff --git a/shaders/glsl/vulkanscene/skybox.frag b/shaders/glsl/vulkanscene/skybox.frag deleted file mode 100644 index 56b8f42c..00000000 --- a/shaders/glsl/vulkanscene/skybox.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (binding = 1) uniform samplerCube samplerCubeMap; - -layout (location = 0) in vec3 inUVW; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(samplerCubeMap, inUVW); -} \ No newline at end of file diff --git a/shaders/glsl/vulkanscene/skybox.frag.spv b/shaders/glsl/vulkanscene/skybox.frag.spv deleted file mode 100644 index 54a894cc..00000000 Binary files a/shaders/glsl/vulkanscene/skybox.frag.spv and /dev/null differ diff --git a/shaders/glsl/vulkanscene/skybox.vert b/shaders/glsl/vulkanscene/skybox.vert deleted file mode 100644 index 89522cc5..00000000 --- a/shaders/glsl/vulkanscene/skybox.vert +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 inPos; - -layout (binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 normal; - mat4 view; -} ubo; - -layout (location = 0) out vec3 outUVW; - -void main() -{ - outUVW = inPos; - // Remove translation from view matrix - mat4 viewMat = mat4(mat3(ubo.view)); - gl_Position = ubo.projection * viewMat * ubo.model * vec4(inPos.xyz, 1.0); -} diff --git a/shaders/glsl/vulkanscene/skybox.vert.spv b/shaders/glsl/vulkanscene/skybox.vert.spv deleted file mode 100644 index 3ce15e1c..00000000 Binary files a/shaders/glsl/vulkanscene/skybox.vert.spv and /dev/null differ diff --git a/shaders/hlsl/README.md b/shaders/hlsl/README.md deleted file mode 100644 index dd70e74a..00000000 --- a/shaders/hlsl/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## HLSL Shaders - -This directory contains shaders using the [HLSL shading language](https://docs.vulkan.org/guide/latest/hlsl.html). These can be compiled with [DXC](https://github.com/microsoft/DirectXShaderCompiler) using e.g. the included `compile.py` script. - -### Known issues - -- Specialization constants can't be used to specify array size. -- `gl_PointCoord` not supported. HLSL has no equivalent. We changed the shaders to calulate the PointCoord manually in the shader. (`computenbody`, `computeparticles`, `particlesystem` examples). -- HLSL doesn't have inverse operation (`deferred`, `hdr`, `instancing`, `skeletalanimation` & `texturecubemap` examples), these should be done on the CPU -- HLSL interface for sparse residency textures is different from GLSL interface. After translating from HLSL to GLSL the shaders behave slightly different. Most important parts do behave identically though. \ No newline at end of file diff --git a/shaders/hlsl/base/textoverlay.frag b/shaders/hlsl/base/textoverlay.frag deleted file mode 100644 index e9d9ba76..00000000 --- a/shaders/hlsl/base/textoverlay.frag +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureFont : register(t0); -SamplerState samplerFont : register(s0); - -float4 main([[vk::location(0)]]float2 inUV : TEXCOORD0) : SV_TARGET -{ - float color = textureFont.Sample(samplerFont, inUV).r; - return float4(color.xxx, 1.0); -} diff --git a/shaders/hlsl/base/textoverlay.frag.spv b/shaders/hlsl/base/textoverlay.frag.spv deleted file mode 100644 index 46f47ac7..00000000 Binary files a/shaders/hlsl/base/textoverlay.frag.spv and /dev/null differ diff --git a/shaders/hlsl/base/textoverlay.vert b/shaders/hlsl/base/textoverlay.vert deleted file mode 100644 index a040eaaa..00000000 --- a/shaders/hlsl/base/textoverlay.vert +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ - [[vk::location(0)]]float2 Pos : POSITION0; - [[vk::location(1)]]float2 UV : TEXCOORD0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - [[vk::location(0)]]float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = float4(input.Pos, 0.0, 1.0); - output.UV = input.UV; - return output; -} diff --git a/shaders/hlsl/base/textoverlay.vert.spv b/shaders/hlsl/base/textoverlay.vert.spv deleted file mode 100644 index 4870eb42..00000000 Binary files a/shaders/hlsl/base/textoverlay.vert.spv and /dev/null differ diff --git a/shaders/hlsl/base/uioverlay.frag b/shaders/hlsl/base/uioverlay.frag deleted file mode 100644 index 9bec808d..00000000 --- a/shaders/hlsl/base/uioverlay.frag +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D fontTexture : register(t0); -SamplerState fontSampler : register(s0); - -struct VSOutput -{ - [[vk::location(0)]]float2 UV : TEXCOORD0; - [[vk::location(1)]]float4 Color : COLOR0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - return input.Color * fontTexture.Sample(fontSampler, input.UV); -} \ No newline at end of file diff --git a/shaders/hlsl/base/uioverlay.frag.spv b/shaders/hlsl/base/uioverlay.frag.spv deleted file mode 100644 index 282a17fd..00000000 Binary files a/shaders/hlsl/base/uioverlay.frag.spv and /dev/null differ diff --git a/shaders/hlsl/base/uioverlay.vert b/shaders/hlsl/base/uioverlay.vert deleted file mode 100644 index be30fd74..00000000 --- a/shaders/hlsl/base/uioverlay.vert +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ - [[vk::location(0)]]float2 Pos : POSITION0; - [[vk::location(1)]]float2 UV : TEXCOORD0; - [[vk::location(2)]]float4 Color : COLOR0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - [[vk::location(0)]]float2 UV : TEXCOORD0; - [[vk::location(1)]]float4 Color : COLOR0; -}; - -struct PushConstants -{ - float2 scale; - float2 translate; -}; - -[[vk::push_constant]] -PushConstants pushConstants; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = float4(input.Pos * pushConstants.scale + pushConstants.translate, 0.0, 1.0); - output.UV = input.UV; - output.Color = input.Color; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/base/uioverlay.vert.spv b/shaders/hlsl/base/uioverlay.vert.spv deleted file mode 100644 index 77519d6a..00000000 Binary files a/shaders/hlsl/base/uioverlay.vert.spv and /dev/null differ diff --git a/shaders/hlsl/bloom/colorpass.frag b/shaders/hlsl/bloom/colorpass.frag deleted file mode 100644 index 9949fd3f..00000000 --- a/shaders/hlsl/bloom/colorpass.frag +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D colorMapTexture : register(t1); -SamplerState colorMapSampler : register(s1); - -struct VSOutput -{ - [[vk::location(0)]]float3 Color : COLOR0; - [[vk::location(1)]]float2 UV : TEXCOORD0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - return float4(input.Color, 1); -} \ No newline at end of file diff --git a/shaders/hlsl/bloom/colorpass.frag.spv b/shaders/hlsl/bloom/colorpass.frag.spv deleted file mode 100644 index 76316d23..00000000 Binary files a/shaders/hlsl/bloom/colorpass.frag.spv and /dev/null differ diff --git a/shaders/hlsl/bloom/colorpass.vert b/shaders/hlsl/bloom/colorpass.vert deleted file mode 100644 index 53dad1b2..00000000 --- a/shaders/hlsl/bloom/colorpass.vert +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ - [[vk::location(0)]]float4 Pos : POSITION0; - [[vk::location(1)]]float2 UV : TEXCOORD0; - [[vk::location(2)]]float3 Color : COLOR0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - [[vk::location(0)]]float3 Color : COLOR0; - [[vk::location(1)]]float2 UV : TEXCOORD0; -}; - -cbuffer UBO : register(b0) -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - output.Color = input.Color; - output.Pos = mul(projection, mul(view, mul(model, input.Pos))); - return output; -} diff --git a/shaders/hlsl/bloom/colorpass.vert.spv b/shaders/hlsl/bloom/colorpass.vert.spv deleted file mode 100644 index 2ab6cf7c..00000000 Binary files a/shaders/hlsl/bloom/colorpass.vert.spv and /dev/null differ diff --git a/shaders/hlsl/bloom/gaussblur.frag b/shaders/hlsl/bloom/gaussblur.frag deleted file mode 100644 index 5da50569..00000000 --- a/shaders/hlsl/bloom/gaussblur.frag +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -cbuffer UBO : register(b0) -{ - float blurScale; - float blurStrength; -}; - -[[vk::constant_id(0)]] const int blurdirection = 0; - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - float weight[5]; - weight[0] = 0.227027; - weight[1] = 0.1945946; - weight[2] = 0.1216216; - weight[3] = 0.054054; - weight[4] = 0.016216; - - float2 textureSize; - textureColor.GetDimensions(textureSize.x, textureSize.y); - float2 tex_offset = 1.0 / textureSize * blurScale; // gets size of single texel - float3 result = textureColor.Sample(samplerColor, inUV).rgb * weight[0]; // current fragment's contribution - for(int i = 1; i < 5; ++i) - { - if (blurdirection == 1) - { - // H - result += textureColor.Sample(samplerColor, inUV + float2(tex_offset.x * i, 0.0)).rgb * weight[i] * blurStrength; - result += textureColor.Sample(samplerColor, inUV - float2(tex_offset.x * i, 0.0)).rgb * weight[i] * blurStrength; - } - else - { - // V - result += textureColor.Sample(samplerColor, inUV + float2(0.0, tex_offset.y * i)).rgb * weight[i] * blurStrength; - result += textureColor.Sample(samplerColor, inUV - float2(0.0, tex_offset.y * i)).rgb * weight[i] * blurStrength; - } - } - return float4(result, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/bloom/gaussblur.frag.spv b/shaders/hlsl/bloom/gaussblur.frag.spv deleted file mode 100644 index c3cc4cfb..00000000 Binary files a/shaders/hlsl/bloom/gaussblur.frag.spv and /dev/null differ diff --git a/shaders/hlsl/bloom/gaussblur.vert b/shaders/hlsl/bloom/gaussblur.vert deleted file mode 100644 index a9c3d551..00000000 --- a/shaders/hlsl/bloom/gaussblur.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; - [[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/bloom/gaussblur.vert.spv b/shaders/hlsl/bloom/gaussblur.vert.spv deleted file mode 100644 index 46c4b31f..00000000 Binary files a/shaders/hlsl/bloom/gaussblur.vert.spv and /dev/null differ diff --git a/shaders/hlsl/bloom/phongpass.frag b/shaders/hlsl/bloom/phongpass.frag deleted file mode 100644 index 3daed2c2..00000000 --- a/shaders/hlsl/bloom/phongpass.frag +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D colorMapTexture : register(t1); -SamplerState colorMapSampler : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 ambient = float3(0.0f, 0.0f, 0.0f); - - // Adjust light calculations for glow color - if ((input.Color.r >= 0.9) || (input.Color.g >= 0.9) || (input.Color.b >= 0.9)) - { - ambient = input.Color * 0.25; - } - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.75f, 0.75f, 0.75f); - return float4(ambient + diffuse + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/bloom/phongpass.frag.spv b/shaders/hlsl/bloom/phongpass.frag.spv deleted file mode 100644 index eb61f5ba..00000000 Binary files a/shaders/hlsl/bloom/phongpass.frag.spv and /dev/null differ diff --git a/shaders/hlsl/bloom/phongpass.vert b/shaders/hlsl/bloom/phongpass.vert deleted file mode 100644 index 198c77c6..00000000 --- a/shaders/hlsl/bloom/phongpass.vert +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 Normal : NORMAL0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -cbuffer UBO : register(b0) -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(projection, mul(view, mul(model, input.Pos))); - - float3 lightPos = float3(-5.0, -5.0, 0.0); - float4 pos = mul(view, mul(model, input.Pos)); - output.Normal = mul((float4x3)mul(view, model), input.Normal).xyz; - output.LightVec = lightPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} diff --git a/shaders/hlsl/bloom/phongpass.vert.spv b/shaders/hlsl/bloom/phongpass.vert.spv deleted file mode 100644 index ac64d27b..00000000 Binary files a/shaders/hlsl/bloom/phongpass.vert.spv and /dev/null differ diff --git a/shaders/hlsl/bloom/skybox.frag b/shaders/hlsl/bloom/skybox.frag deleted file mode 100644 index 18460ed9..00000000 --- a/shaders/hlsl/bloom/skybox.frag +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureCubeMap : register(t1); -SamplerState samplerCubeMap : register(s1); - -float4 main([[vk::location(0)]] float3 inUVW : NORMAL0) : SV_TARGET -{ - return textureCubeMap.Sample(samplerCubeMap, inUVW); -} \ No newline at end of file diff --git a/shaders/hlsl/bloom/skybox.frag.spv b/shaders/hlsl/bloom/skybox.frag.spv deleted file mode 100644 index d5394a52..00000000 Binary files a/shaders/hlsl/bloom/skybox.frag.spv and /dev/null differ diff --git a/shaders/hlsl/bloom/skybox.vert b/shaders/hlsl/bloom/skybox.vert deleted file mode 100644 index 212e404f..00000000 --- a/shaders/hlsl/bloom/skybox.vert +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 Google LLC - -cbuffer UBO : register(b0) -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - [[vk::location(0)]] float3 UVW : NORMAL0; -}; - -VSOutput main([[vk::location(0)]] float3 inPos : POSITION0) -{ - VSOutput output = (VSOutput)0; - output.UVW = inPos; - output.Pos = mul(projection, mul(view, mul(model, float4(inPos.xyz, 1.0)))); - return output; -} diff --git a/shaders/hlsl/bloom/skybox.vert.spv b/shaders/hlsl/bloom/skybox.vert.spv deleted file mode 100644 index 3e732bbc..00000000 Binary files a/shaders/hlsl/bloom/skybox.vert.spv and /dev/null differ diff --git a/shaders/hlsl/compileshaders.py b/shaders/hlsl/compileshaders.py deleted file mode 100644 index 0e093f26..00000000 --- a/shaders/hlsl/compileshaders.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2020 Google LLC -# Copyright 2023-2024 Sascha Willems - -import argparse -import fileinput -import os -import subprocess -import sys - -parser = argparse.ArgumentParser(description='Compile all .hlsl shaders') -parser.add_argument('--dxc', type=str, help='path to DXC executable') -args = parser.parse_args() - -def findDXC(): - def isExe(path): - return os.path.isfile(path) and os.access(path, os.X_OK) - - if args.dxc != None and isExe(args.dxc): - return args.dxc - - exe_name = "dxc" - if os.name == "nt": - exe_name += ".exe" - - for exe_dir in os.environ["PATH"].split(os.pathsep): - full_path = os.path.join(exe_dir, exe_name) - if isExe(full_path): - return full_path - - sys.exit("Could not find DXC executable on PATH, and was not specified with --dxc") - -file_extensions = tuple([".vert", ".frag", ".comp", ".geom", ".tesc", ".tese", ".rgen", ".rchit", ".rmiss", ".mesh", ".task"]) - -dxc_path = findDXC() -dir_path = os.path.dirname(os.path.realpath(__file__)) -dir_path = dir_path.replace('\\', '/') -for root, dirs, files in os.walk(dir_path): - for file in files: - if file.endswith(file_extensions): - hlsl_file = os.path.join(root, file) - spv_out = hlsl_file + ".spv" - - target = '' - profile = '' - additional_exts = '' - if(hlsl_file.find('.vert') != -1): - profile = 'vs_6_1' - elif(hlsl_file.find('.frag') != -1): - profile = 'ps_6_4' - elif(hlsl_file.find('.comp') != -1): - profile = 'cs_6_1' - elif(hlsl_file.find('.geom') != -1): - profile = 'gs_6_1' - elif(hlsl_file.find('.tesc') != -1): - profile = 'hs_6_1' - elif(hlsl_file.find('.tese') != -1): - profile = 'ds_6_1' - elif(hlsl_file.find('.rgen') != -1 or - hlsl_file.find('.rchit') != -1 or - hlsl_file.find('.rmiss') != -1): - target='-fspv-target-env=vulkan1.2' - profile = 'lib_6_3' - elif(hlsl_file.find('.mesh') != -1): - target='-fspv-target-env=vulkan1.2' - additional_exts = '-fspv-extension=SPV_EXT_mesh_shader' - profile = 'ms_6_6' - elif(hlsl_file.find('.task') != -1): - target='-fspv-target-env=vulkan1.2' - additional_exts = '-fspv-extension=SPV_EXT_mesh_shader' - profile = 'as_6_6' - - if root.endswith("debugprintf"): - additional_exts = '-fspv-extension=SPV_KHR_non_semantic_info' - - print('Compiling %s' % (hlsl_file)) - subprocess.check_output([ - dxc_path, - '-spirv', - '-T', profile, - '-E', 'main', - '-fspv-extension=SPV_KHR_ray_tracing', - '-fspv-extension=SPV_KHR_multiview', - '-fspv-extension=SPV_KHR_shader_draw_parameters', - '-fspv-extension=SPV_EXT_descriptor_indexing', - '-fspv-extension=SPV_KHR_ray_query', - '-fspv-extension=SPV_KHR_fragment_shading_rate', - additional_exts, - target, - hlsl_file, - '-Fo', spv_out]) diff --git a/shaders/hlsl/computecloth/cloth.comp b/shaders/hlsl/computecloth/cloth.comp deleted file mode 100644 index b09dbae1..00000000 --- a/shaders/hlsl/computecloth/cloth.comp +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2023 Sascha Willems - -struct Particle { - float4 pos; - float4 vel; - float4 uv; - float4 normal; -}; - -[[vk::binding(0)]] -StructuredBuffer particleIn; -[[vk::binding(1)]] -RWStructuredBuffer particleOut; - -struct UBO -{ - float deltaT; - float particleMass; - float springStiffness; - float damping; - float restDistH; - float restDistV; - float restDistD; - float sphereRadius; - float4 spherePos; - float4 gravity; - int2 particleCount; -}; - -cbuffer ubo : register(b2) -{ - UBO params; -}; - -struct PushConstants -{ - uint calculateNormals; -}; - -[[vk::push_constant]] -PushConstants pushConstants; - -float3 springForce(float3 p0, float3 p1, float restDist) -{ - float3 dist = p0 - p1; - return normalize(dist) * params.springStiffness * (length(dist) - restDist); -} - -[numthreads(10, 10, 1)] -void main(uint3 id : SV_DispatchThreadID) -{ - uint index = id.y * params.particleCount.x + id.x; - if (index > params.particleCount.x * params.particleCount.y) - return; - - // Initial force from gravity - float3 force = params.gravity.xyz * params.particleMass; - - float3 pos = particleIn[index].pos.xyz; - float3 vel = particleIn[index].vel.xyz; - - // Spring forces from neighboring particles - // left - if (id.x > 0) { - force += springForce(particleIn[index-1].pos.xyz, pos, params.restDistH); - } - // right - if (id.x < params.particleCount.x - 1) { - force += springForce(particleIn[index + 1].pos.xyz, pos, params.restDistH); - } - // upper - if (id.y < params.particleCount.y - 1) { - force += springForce(particleIn[index + params.particleCount.x].pos.xyz, pos, params.restDistV); - } - // lower - if (id.y > 0) { - force += springForce(particleIn[index - params.particleCount.x].pos.xyz, pos, params.restDistV); - } - // upper-left - if ((id.x > 0) && (id.y < params.particleCount.y - 1)) { - force += springForce(particleIn[index + params.particleCount.x - 1].pos.xyz, pos, params.restDistD); - } - // lower-left - if ((id.x > 0) && (id.y > 0)) { - force += springForce(particleIn[index - params.particleCount.x - 1].pos.xyz, pos, params.restDistD); - } - // upper-right - if ((id.x < params.particleCount.x - 1) && (id.y < params.particleCount.y - 1)) { - force += springForce(particleIn[index + params.particleCount.x + 1].pos.xyz, pos, params.restDistD); - } - // lower-right - if ((id.x < params.particleCount.x - 1) && (id.y > 0)) { - force += springForce(particleIn[index - params.particleCount.x + 1].pos.xyz, pos, params.restDistD); - } - - force += (-params.damping * vel); - - // Integrate - float3 f = force * (1.0 / params.particleMass); - particleOut[index].pos = float4(pos + vel * params.deltaT + 0.5 * f * params.deltaT * params.deltaT, 1.0); - particleOut[index].vel = float4(vel + f * params.deltaT, 0.0); - - // Sphere collision - float3 sphereDist = particleOut[index].pos.xyz - params.spherePos.xyz; - if (length(sphereDist) < params.sphereRadius + 0.01) { - // If the particle is inside the sphere, push it to the outer radius - particleOut[index].pos.xyz = params.spherePos.xyz + normalize(sphereDist) * (params.sphereRadius + 0.01); - // Cancel out velocity - particleOut[index].vel = float4(0, 0, 0, 0); - } - - // Normals - if (pushConstants.calculateNormals == 1) { - float3 normal = float3(0, 0, 0); - float3 a, b, c; - if (id.y > 0) { - if (id.x > 0) { - a = particleIn[index - 1].pos.xyz - pos; - b = particleIn[index - params.particleCount.x - 1].pos.xyz - pos; - c = particleIn[index - params.particleCount.x].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - if (id.x < params.particleCount.x - 1) { - a = particleIn[index - params.particleCount.x].pos.xyz - pos; - b = particleIn[index - params.particleCount.x + 1].pos.xyz - pos; - c = particleIn[index + 1].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - } - if (id.y < params.particleCount.y - 1) { - if (id.x > 0) { - a = particleIn[index + params.particleCount.x].pos.xyz - pos; - b = particleIn[index + params.particleCount.x - 1].pos.xyz - pos; - c = particleIn[index - 1].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - if (id.x < params.particleCount.x - 1) { - a = particleIn[index + 1].pos.xyz - pos; - b = particleIn[index + params.particleCount.x + 1].pos.xyz - pos; - c = particleIn[index + params.particleCount.x].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - } - particleOut[index].normal = float4(normalize(normal), 0.0f); - } -} \ No newline at end of file diff --git a/shaders/hlsl/computecloth/cloth.comp.spv b/shaders/hlsl/computecloth/cloth.comp.spv deleted file mode 100644 index 5e85d78b..00000000 Binary files a/shaders/hlsl/computecloth/cloth.comp.spv and /dev/null differ diff --git a/shaders/hlsl/computecloth/cloth.frag b/shaders/hlsl/computecloth/cloth.frag deleted file mode 100644 index 46612dc3..00000000 --- a/shaders/hlsl/computecloth/cloth.frag +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -struct VSOutput -{ -[[vk::location(0)]]float2 UV : TEXCOORD0; -[[vk::location(1)]]float3 Normal : NORMAL0; -[[vk::location(2)]]float3 ViewVec : TEXCOORD1; -[[vk::location(3)]]float3 LightVec : TEXCOORD2; -}; - -float4 main (VSOutput input) : SV_TARGET -{ - float3 color = textureColor.Sample(samplerColor, input.UV).rgb; - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.15) * float3(1, 1, 1); - float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.2, 0.2, 0.2); - return float4(diffuse * color.rgb + specular, 1.0); -} diff --git a/shaders/hlsl/computecloth/cloth.frag.spv b/shaders/hlsl/computecloth/cloth.frag.spv deleted file mode 100644 index 7a81f354..00000000 Binary files a/shaders/hlsl/computecloth/cloth.frag.spv and /dev/null differ diff --git a/shaders/hlsl/computecloth/cloth.vert b/shaders/hlsl/computecloth/cloth.vert deleted file mode 100644 index 00d46927..00000000 --- a/shaders/hlsl/computecloth/cloth.vert +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Normal : NORMAL0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; -}; - -cbuffer ubo : register(b0) -{ - UBO ubo; -}; - -VSOutput main (VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - output.Normal = input.Normal.xyz; - float4 eyePos = mul(ubo.modelview, float4(input.Pos.x, input.Pos.y, input.Pos.z, 1.0)); - output.Pos = mul(ubo.projection, eyePos); - float4 pos = float4(input.Pos, 1.0); - float3 lPos = ubo.lightPos.xyz; - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/computecloth/cloth.vert.spv b/shaders/hlsl/computecloth/cloth.vert.spv deleted file mode 100644 index 5e2dcb53..00000000 Binary files a/shaders/hlsl/computecloth/cloth.vert.spv and /dev/null differ diff --git a/shaders/hlsl/computecloth/sphere.frag b/shaders/hlsl/computecloth/sphere.frag deleted file mode 100644 index 207db7aa..00000000 --- a/shaders/hlsl/computecloth/sphere.frag +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 ViewVec : TEXCOORD0; -[[vk::location(2)]] float3 LightVec : TEXCOORD1; -}; - -float4 main (VSOutput input) : SV_TARGET -{ - float3 color = float3(0.5, 0.5, 0.5); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.15); - float3 specular = pow(max(dot(R, V), 0.0), 32.0); - return float4(diffuse * color.rgb + specular, 1.0); -} diff --git a/shaders/hlsl/computecloth/sphere.frag.spv b/shaders/hlsl/computecloth/sphere.frag.spv deleted file mode 100644 index fbb448bf..00000000 Binary files a/shaders/hlsl/computecloth/sphere.frag.spv and /dev/null differ diff --git a/shaders/hlsl/computecloth/sphere.vert b/shaders/hlsl/computecloth/sphere.vert deleted file mode 100644 index 8414cb58..00000000 --- a/shaders/hlsl/computecloth/sphere.vert +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]]float3 Pos : POSITION0; -[[vk::location(2)]]float3 Normal : NORMAL0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 ViewVec : TEXCOORD0; -[[vk::location(2)]] float3 LightVec : TEXCOORD1; -}; - - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; -}; - -cbuffer ubo : register(b0) -{ - UBO ubo; -}; - -VSOutput main (VSInput input) -{ - VSOutput output = (VSOutput)0; - float4 eyePos = mul(ubo.modelview, float4(input.Pos.x, input.Pos.y, input.Pos.z, 1.0)); - output.Pos = mul(ubo.projection, eyePos); - float4 pos = float4(input.Pos, 1.0); - float3 lPos = ubo.lightPos.xyz; - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - output.Normal = input.Normal; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/computecloth/sphere.vert.spv b/shaders/hlsl/computecloth/sphere.vert.spv deleted file mode 100644 index a8803b0f..00000000 Binary files a/shaders/hlsl/computecloth/sphere.vert.spv and /dev/null differ diff --git a/shaders/hlsl/computecullandlod/cull.comp b/shaders/hlsl/computecullandlod/cull.comp deleted file mode 100644 index 39d70c74..00000000 --- a/shaders/hlsl/computecullandlod/cull.comp +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2020 Google LLC - -#define MAX_LOD_LEVEL_COUNT 6 -[[vk::constant_id(0)]] const int MAX_LOD_LEVEL = 5; - -struct InstanceData -{ - float3 pos; - float scale; -}; - -StructuredBuffer instances : register(t0); - -// Same layout as VkDrawIndexedIndirectCommand -struct IndexedIndirectCommand -{ - uint indexCount; - uint instanceCount; - uint firstIndex; - uint vertexOffset; - uint firstInstance; -}; - -RWStructuredBuffer indirectDraws : register(u1); - -// Binding 2: Uniform block object with matrices -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 cameraPos; - float4 frustumPlanes[6]; -}; - -cbuffer ubo : register(b2) { UBO ubo; } - -// Binding 3: Indirect draw stats -struct UBOOut -{ - uint drawCount; - uint lodCount[MAX_LOD_LEVEL_COUNT]; -}; -RWStructuredBuffer uboOut : register(u3); - -// Binding 4: level-of-detail information -struct LOD -{ - uint firstIndex; - uint indexCount; - float distance; - float _pad0; -}; - -StructuredBuffer lods : register(t4); - -[numthreads(16, 1, 1)] -bool frustumCheck(float4 pos, float radius) -{ - // Check sphere against frustum planes - for (int i = 0; i < 6; i++) - { - if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0) - { - return false; - } - } - return true; -} - -[numthreads(16, 1, 1)] -void main(uint3 GlobalInvocationID : SV_DispatchThreadID ) -{ - uint idx = GlobalInvocationID.x; - uint temp; - - // Clear stats on first invocation - if (idx == 0) - { - InterlockedExchange(uboOut[0].drawCount, 0, temp); - for (uint i = 0; i < MAX_LOD_LEVEL + 1; i++) - { - InterlockedExchange(uboOut[0].lodCount[i], 0, temp); - } - } - - float4 pos = float4(instances[idx].pos.xyz, 1.0); - - // Check if object is within current viewing frustum - if (frustumCheck(pos, 1.0)) - { - indirectDraws[idx].instanceCount = 1; - - // Increase number of indirect draw counts - InterlockedAdd(uboOut[0].drawCount, 1, temp); - - // Select appropriate LOD level based on distance to camera - uint lodLevel = MAX_LOD_LEVEL; - for (uint i = 0; i < MAX_LOD_LEVEL; i++) - { - if (distance(instances[idx].pos.xyz, ubo.cameraPos.xyz) < lods[i].distance) - { - lodLevel = i; - break; - } - } - indirectDraws[idx].firstIndex = lods[lodLevel].firstIndex; - indirectDraws[idx].indexCount = lods[lodLevel].indexCount; - // Update stats - InterlockedAdd(uboOut[0].lodCount[lodLevel], 1, temp); - } - else - { - indirectDraws[idx].instanceCount = 0; - } -} \ No newline at end of file diff --git a/shaders/hlsl/computecullandlod/cull.comp.spv b/shaders/hlsl/computecullandlod/cull.comp.spv deleted file mode 100644 index bfaf7a66..00000000 Binary files a/shaders/hlsl/computecullandlod/cull.comp.spv and /dev/null differ diff --git a/shaders/hlsl/computecullandlod/indirectdraw.frag b/shaders/hlsl/computecullandlod/indirectdraw.frag deleted file mode 100644 index f4f49dab..00000000 --- a/shaders/hlsl/computecullandlod/indirectdraw.frag +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 ambient = float3(0.25, 0.25, 0.25); - float3 diffuse = max(dot(N, L), 0.0).xxx; - return float4((ambient + diffuse) * input.Color, 1.0); -} diff --git a/shaders/hlsl/computecullandlod/indirectdraw.frag.spv b/shaders/hlsl/computecullandlod/indirectdraw.frag.spv deleted file mode 100644 index 6d46b407..00000000 Binary files a/shaders/hlsl/computecullandlod/indirectdraw.frag.spv and /dev/null differ diff --git a/shaders/hlsl/computecullandlod/indirectdraw.vert b/shaders/hlsl/computecullandlod/indirectdraw.vert deleted file mode 100644 index 06bcbe1b..00000000 --- a/shaders/hlsl/computecullandlod/indirectdraw.vert +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -// Instanced attributes -[[vk::location(3)]] float3 instancePos : TEXCOORD0; -[[vk::location(4)]] float instanceScale : TEXCOORD1; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - - output.Normal = input.Normal; - - float4 pos = float4((input.Pos.xyz * input.instanceScale) + input.instancePos, 1.0); - - output.Pos = mul(ubo.projection, mul(ubo.modelview, pos)); - - float4 wPos = mul(ubo.modelview, float4(pos.xyz, 1.0)); - float4 lPos = float4(0.0, 10.0, 50.0, 1.0); - output.LightVec = lPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} diff --git a/shaders/hlsl/computecullandlod/indirectdraw.vert.spv b/shaders/hlsl/computecullandlod/indirectdraw.vert.spv deleted file mode 100644 index 63b0ea60..00000000 Binary files a/shaders/hlsl/computecullandlod/indirectdraw.vert.spv and /dev/null differ diff --git a/shaders/hlsl/computeheadless/headless.comp b/shaders/hlsl/computeheadless/headless.comp deleted file mode 100644 index 827f9159..00000000 --- a/shaders/hlsl/computeheadless/headless.comp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2020 Google LLC - -RWStructuredBuffer values : register(u0); -[[vk::constant_id(0)]] const uint BUFFER_ELEMENTS = 32; - -uint fibonacci(uint n) { - if(n <= 1){ - return n; - } - uint curr = 1; - uint prev = 1; - for(uint i = 2; i < n; ++i) { - uint temp = curr; - curr += prev; - prev = temp; - } - return curr; -} - -[numthreads(1, 1, 1)] -void main(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - uint index = GlobalInvocationID.x; - if (index >= BUFFER_ELEMENTS) - return; - values[index] = fibonacci(values[index]); -} - diff --git a/shaders/hlsl/computeheadless/headless.comp.spv b/shaders/hlsl/computeheadless/headless.comp.spv deleted file mode 100644 index cf111a2d..00000000 Binary files a/shaders/hlsl/computeheadless/headless.comp.spv and /dev/null differ diff --git a/shaders/hlsl/computenbody/particle.frag b/shaders/hlsl/computenbody/particle.frag deleted file mode 100644 index dd7bd3b8..00000000 --- a/shaders/hlsl/computenbody/particle.frag +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t0); -SamplerState samplerColorMap : register(s0); -Texture2D textureGradientRamp : register(t1); -SamplerState samplerGradientRamp : register(s1); - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float GradientPos : POSITION0; -[[vk::location(1)]] float2 CenterPos : POSITION1; -[[vk::location(2)]] float PointSize : TEXCOORD0; -}; - -float4 main (VSOutput input) : SV_TARGET -{ - float3 color = textureGradientRamp.Sample(samplerGradientRamp, float2(input.GradientPos, 0.0)).rgb; - float2 PointCoord = (input.Pos.xy - input.CenterPos.xy) / input.PointSize + 0.5; - return float4(textureColorMap.Sample(samplerColorMap, PointCoord).rgb * color, 1); -} diff --git a/shaders/hlsl/computenbody/particle.frag.spv b/shaders/hlsl/computenbody/particle.frag.spv deleted file mode 100644 index 0304c993..00000000 Binary files a/shaders/hlsl/computenbody/particle.frag.spv and /dev/null differ diff --git a/shaders/hlsl/computenbody/particle.vert b/shaders/hlsl/computenbody/particle.vert deleted file mode 100644 index b2a76596..00000000 --- a/shaders/hlsl/computenbody/particle.vert +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float4 Vel : TEXCOORD0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float GradientPos : POSITION0; -[[vk::location(1)]] float2 CenterPos : POSITION1; -[[vk::builtin("PointSize")]] float PSize : PSIZE; -[[vk::location(2)]] float PointSize : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float2 screendim; -}; - -cbuffer ubo : register(b2) { UBO ubo; } - -VSOutput main (VSInput input) -{ - VSOutput output = (VSOutput)0; - const float spriteSize = 0.005 * input.Pos.w; // Point size influenced by mass (stored in input.Pos.w); - - float4 eyePos = mul(ubo.modelview, float4(input.Pos.x, input.Pos.y, input.Pos.z, 1.0)); - float4 projectedCorner = mul(ubo.projection, float4(0.5 * spriteSize, 0.5 * spriteSize, eyePos.z, eyePos.w)); - output.PSize = output.PointSize = clamp(ubo.screendim.x * projectedCorner.x / projectedCorner.w, 1.0, 128.0); - - output.Pos = mul(ubo.projection, eyePos); - output.CenterPos = ((output.Pos.xy / output.Pos.w) + 1.0) * 0.5 * ubo.screendim; - - output.GradientPos = input.Vel.w; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/computenbody/particle.vert.spv b/shaders/hlsl/computenbody/particle.vert.spv deleted file mode 100644 index df56eaae..00000000 Binary files a/shaders/hlsl/computenbody/particle.vert.spv and /dev/null differ diff --git a/shaders/hlsl/computenbody/particle_calculate.comp b/shaders/hlsl/computenbody/particle_calculate.comp deleted file mode 100644 index 3b1bc85b..00000000 --- a/shaders/hlsl/computenbody/particle_calculate.comp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2023 Sascha Willems - -struct Particle -{ - float4 pos; - float4 vel; -}; - -// Binding 0 : Position storage buffer -RWStructuredBuffer particles : register(u0); - -struct UBO -{ - float deltaT; - int particleCount; - float gravity; - float power; - float soften; -}; - -cbuffer ubo : register(b1) { UBO ubo; } - -#define MAX_SHARED_DATA_SIZE 1024 -[[vk::constant_id(0)]] const int SHARED_DATA_SIZE = 512; -[[vk::constant_id(1)]] const float GRAVITY = 0.002; -[[vk::constant_id(2)]] const float POWER = 0.75; -[[vk::constant_id(3)]] const float SOFTEN = 0.0075; - -// Share data between computer shader invocations to speed up caluclations -groupshared float4 sharedData[MAX_SHARED_DATA_SIZE]; - -[numthreads(256, 1, 1)] -void main(uint3 GlobalInvocationID : SV_DispatchThreadID, uint3 LocalInvocationID : SV_GroupThreadID) -{ - // Current SSBO index - uint index = GlobalInvocationID.x; - if (index >= ubo.particleCount) - return; - - float4 position = particles[index].pos; - float4 velocity = particles[index].vel; - float4 acceleration = float4(0, 0, 0, 0); - - for (int i = 0; i < ubo.particleCount; i += SHARED_DATA_SIZE) - { - if (i + LocalInvocationID.x < ubo.particleCount) - { - sharedData[LocalInvocationID.x] = particles[i + LocalInvocationID.x].pos; - } - else - { - sharedData[LocalInvocationID.x] = float4(0, 0, 0, 0); - } - - GroupMemoryBarrierWithGroupSync(); - - for (int j = 0; j < 256; j++) - { - float4 other = sharedData[j]; - float3 len = other.xyz - position.xyz; - acceleration.xyz += ubo.gravity * len * other.w / pow(dot(len, len) + ubo.soften, ubo.power); - } - - GroupMemoryBarrierWithGroupSync(); - } - - particles[index].vel.xyz += ubo.deltaT * acceleration.xyz; - - // Gradient texture position - particles[index].vel.w += 0.1 * ubo.deltaT; - if (particles[index].vel.w > 1.0) { - particles[index].vel.w -= 1.0; - } -} \ No newline at end of file diff --git a/shaders/hlsl/computenbody/particle_calculate.comp.spv b/shaders/hlsl/computenbody/particle_calculate.comp.spv deleted file mode 100644 index 58d790a3..00000000 Binary files a/shaders/hlsl/computenbody/particle_calculate.comp.spv and /dev/null differ diff --git a/shaders/hlsl/computenbody/particle_integrate.comp b/shaders/hlsl/computenbody/particle_integrate.comp deleted file mode 100644 index 90065a5b..00000000 --- a/shaders/hlsl/computenbody/particle_integrate.comp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2020 Google LLC - -struct Particle -{ - float4 pos; - float4 vel; -}; - -// Binding 0 : Position storage buffer -RWStructuredBuffer particles : register(u0); - -struct UBO -{ - float deltaT; - int particleCount; -}; - -cbuffer ubo : register(b1) { UBO ubo; } - -[numthreads(256, 1, 1)] -void main(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - int index = int(GlobalInvocationID.x); - float4 position = particles[index].pos; - float4 velocity = particles[index].vel; - position += ubo.deltaT * velocity; - particles[index].pos = position; -} \ No newline at end of file diff --git a/shaders/hlsl/computenbody/particle_integrate.comp.spv b/shaders/hlsl/computenbody/particle_integrate.comp.spv deleted file mode 100644 index 22e22b91..00000000 Binary files a/shaders/hlsl/computenbody/particle_integrate.comp.spv and /dev/null differ diff --git a/shaders/hlsl/computeparticles/particle.comp b/shaders/hlsl/computeparticles/particle.comp deleted file mode 100644 index 940faffb..00000000 --- a/shaders/hlsl/computeparticles/particle.comp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2020 Google LLC - -struct Particle -{ - float2 pos; - float2 vel; - float4 gradientPos; -}; - -// Binding 0 : Position storage buffer -RWStructuredBuffer particles : register(u0); - -struct UBO -{ - float deltaT; - float destX; - float destY; - int particleCount; -}; - -cbuffer ubo : register(b1) { UBO ubo; } - -float2 attraction(float2 pos, float2 attractPos) -{ - float2 delta = attractPos - pos; - const float damp = 0.5; - float dDampedDot = dot(delta, delta) + damp; - float invDist = 1.0f / sqrt(dDampedDot); - float invDistCubed = invDist*invDist*invDist; - return delta * invDistCubed * 0.0035; -} - -float2 repulsion(float2 pos, float2 attractPos) -{ - float2 delta = attractPos - pos; - float targetDistance = sqrt(dot(delta, delta)); - return delta * (1.0 / (targetDistance * targetDistance * targetDistance)) * -0.000035; -} - -[numthreads(256, 1, 1)] -void main(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - // Current SSBO index - uint index = GlobalInvocationID.x; - // Don't try to write beyond particle count - if (index >= ubo.particleCount) - return; - - // Read position and velocity - float2 vVel = particles[index].vel.xy; - float2 vPos = particles[index].pos.xy; - - float2 destPos = float2(ubo.destX, ubo.destY); - - float2 delta = destPos - vPos; - float targetDistance = sqrt(dot(delta, delta)); - vVel += repulsion(vPos, destPos.xy) * 0.05; - - // Move by velocity - vPos += vVel * ubo.deltaT; - - // collide with boundary - if ((vPos.x < -1.0) || (vPos.x > 1.0) || (vPos.y < -1.0) || (vPos.y > 1.0)) - vVel = (-vVel * 0.1) + attraction(vPos, destPos) * 12; - else - particles[index].pos.xy = vPos; - - // Write back - particles[index].vel.xy = vVel; - particles[index].gradientPos.x += 0.02 * ubo.deltaT; - if (particles[index].gradientPos.x > 1.0) - particles[index].gradientPos.x -= 1.0; -} - diff --git a/shaders/hlsl/computeparticles/particle.comp.spv b/shaders/hlsl/computeparticles/particle.comp.spv deleted file mode 100644 index 7a04747d..00000000 Binary files a/shaders/hlsl/computeparticles/particle.comp.spv and /dev/null differ diff --git a/shaders/hlsl/computeparticles/particle.frag b/shaders/hlsl/computeparticles/particle.frag deleted file mode 100644 index f3c386f8..00000000 --- a/shaders/hlsl/computeparticles/particle.frag +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t0); -SamplerState samplerColorMap : register(s0); -Texture2D textureGradientRamp : register(t1); -SamplerState samplerGradientRamp : register(s1); - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float4 Color : COLOR0; -[[vk::location(1)]] float GradientPos : POSITION0; -[[vk::location(2)]] float2 CenterPos : POSITION1; -[[vk::location(3)]] float PointSize : TEXCOORD0; -}; - -float4 main (VSOutput input) : SV_TARGET -{ - float3 color = textureGradientRamp.Sample(samplerGradientRamp, float2(input.GradientPos, 0.0)).rgb; - float2 PointCoord = (input.Pos.xy - input.CenterPos.xy) / input.PointSize + 0.5; - return float4(textureColorMap.Sample(samplerColorMap, PointCoord).rgb * color, 1.0); -} diff --git a/shaders/hlsl/computeparticles/particle.frag.spv b/shaders/hlsl/computeparticles/particle.frag.spv deleted file mode 100644 index f976843b..00000000 Binary files a/shaders/hlsl/computeparticles/particle.frag.spv and /dev/null differ diff --git a/shaders/hlsl/computeparticles/particle.vert b/shaders/hlsl/computeparticles/particle.vert deleted file mode 100644 index a19c5990..00000000 --- a/shaders/hlsl/computeparticles/particle.vert +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float2 Pos : POSITION0; -[[vk::location(1)]] float4 GradientPos : POSITION1; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::builtin("PointSize")]] float PSize : PSIZE; -[[vk::location(0)]] float4 Color : COLOR0; -[[vk::location(1)]] float GradientPos : POSITION0; -[[vk::location(2)]] float2 CenterPos : POSITION1; -[[vk::location(3)]] float PointSize : TEXCOORD0; -}; - -struct PushConsts -{ - float2 screendim; -}; - -[[vk::push_constant]] PushConsts pushConstants; - -VSOutput main (VSInput input) -{ - VSOutput output = (VSOutput)0; - output.PSize = output.PointSize = 8.0; - output.Color = float4(0.035, 0.035, 0.035, 0.035); - output.GradientPos = input.GradientPos.x; - output.Pos = float4(input.Pos.xy, 1.0, 1.0); - output.CenterPos = ((output.Pos.xy / output.Pos.w) + 1.0) * 0.5 * pushConstants.screendim; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/computeparticles/particle.vert.spv b/shaders/hlsl/computeparticles/particle.vert.spv deleted file mode 100644 index 78ce9e1c..00000000 Binary files a/shaders/hlsl/computeparticles/particle.vert.spv and /dev/null differ diff --git a/shaders/hlsl/computeraytracing/raytracing.comp b/shaders/hlsl/computeraytracing/raytracing.comp deleted file mode 100644 index d1842398..00000000 --- a/shaders/hlsl/computeraytracing/raytracing.comp +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2023 Sascha Willems - -// Shader is looseley based on the ray tracing coding session by Inigo Quilez (www.iquilezles.org) - -RWTexture2D resultImage : register(u0); - -#define EPSILON 0.0001 -#define MAXLEN 1000.0 -#define SHADOW 0.5 -#define RAYBOUNCES 2 -#define REFLECTIONS true -#define REFLECTIONSTRENGTH 0.4 -#define REFLECTIONFALLOFF 0.5 - -#define SceneObjectTypeSphere 0 -#define SceneObjectTypePlane 1 - -struct Camera -{ - float3 pos; - float3 lookat; - float fov; -}; - -struct UBO -{ - float3 lightPos; - float aspectRatio; - float4 fogColor; - Camera camera; - float4x4 rotMat; -}; - -cbuffer ubo : register(b1) { UBO ubo; } - -struct SceneObject -{ - float4 objectProperties; - float3 diffuse; - float specular; - int id; - int objectType; -}; - -StructuredBuffer sceneObjects : register(t2); - -void reflectRay(inout float3 rayD, in float3 mormal) -{ - rayD = rayD + 2.0 * -dot(mormal, rayD) * mormal; -} - -// Lighting ========================================================= - -float lightDiffuse(float3 normal, float3 lightDir) -{ - return clamp(dot(normal, lightDir), 0.1, 1.0); -} - -float lightSpecular(float3 normal, float3 lightDir, float specularFactor) -{ - float3 viewVec = normalize(ubo.camera.pos); - float3 halfVec = normalize(lightDir + viewVec); - return pow(clamp(dot(normal, halfVec), 0.0, 1.0), specularFactor); -} - -// Sphere =========================================================== - -float sphereIntersect(in float3 rayO, in float3 rayD, in SceneObject sphere) -{ - float3 oc = rayO - sphere.objectProperties.xyz; - float b = 2.0 * dot(oc, rayD); - float c = dot(oc, oc) - sphere.objectProperties.w * sphere.objectProperties.w; - float h = b*b - 4.0*c; - if (h < 0.0) - { - return -1.0; - } - float t = (-b - sqrt(h)) / 2.0; - - return t; -} - -float3 sphereNormal(in float3 pos, in SceneObject sphere) -{ - return (pos - sphere.objectProperties.xyz) / sphere.objectProperties.w; -} - -// Plane =========================================================== - -float planeIntersect(float3 rayO, float3 rayD, SceneObject plane) -{ - float d = dot(rayD, plane.objectProperties.xyz); - - if (d == 0.0) - return 0.0; - - float t = -(plane.objectProperties.w + dot(rayO, plane.objectProperties.xyz)) / d; - - if (t < 0.0) - return 0.0; - - return t; -} - - -int intersect(in float3 rayO, in float3 rayD, inout float resT) -{ - int id = -1; - float t = MAXLEN; - - uint sceneObjectsLength; - uint sceneObjectsStride; - sceneObjects.GetDimensions(sceneObjectsLength, sceneObjectsStride); - - for (int i = 0; i < sceneObjectsLength; i++) { - // Sphere - if (sceneObjects[i].objectType == SceneObjectTypeSphere) { - t = sphereIntersect(rayO, rayD, sceneObjects[i]); - } - // Plane - if (sceneObjects[i].objectType == SceneObjectTypePlane) { - t = planeIntersect(rayO, rayD, sceneObjects[i]); - } - if ((t > EPSILON) && (t < resT)) - { - id = sceneObjects[i].id; - resT = t; - } - } - - return id; -} - -float calcShadow(in float3 rayO, in float3 rayD, in int objectId, inout float t) -{ - uint sceneObjectsLength; - uint sceneObjectsStride; - sceneObjects.GetDimensions(sceneObjectsLength, sceneObjectsStride); - - for (int i = 0; i < sceneObjectsLength; i++) { - if (sceneObjects[i].id == objectId) - continue; - - float tLoc = MAXLEN; - - // Sphere - if (sceneObjects[i].objectType == SceneObjectTypeSphere) - { - tLoc = sphereIntersect(rayO, rayD, sceneObjects[i]); - } - // Plane - if (sceneObjects[i].objectType == SceneObjectTypePlane) - { - tLoc = planeIntersect(rayO, rayD, sceneObjects[i]); - } - if ((tLoc > EPSILON) && (tLoc < t)) - { - t = tLoc; - return SHADOW; - } - } - return 1.0; -} - -float3 fog(in float t, in float3 color) -{ - return lerp(color, ubo.fogColor.rgb, clamp(sqrt(t*t)/20.0, 0.0, 1.0)); -} - -float3 renderScene(inout float3 rayO, inout float3 rayD, inout int id) -{ - float3 color = float3(0, 0, 0); - float t = MAXLEN; - - // Get intersected object ID - int objectID = intersect(rayO, rayD, t); - - if (objectID == -1) - { - return color; - } - - float3 pos = rayO + t * rayD; - float3 lightVec = normalize(ubo.lightPos - pos); - float3 normal; - - uint sceneObjectsLength; - uint sceneObjectsStride; - sceneObjects.GetDimensions(sceneObjectsLength, sceneObjectsStride); - - for (int i = 0; i < sceneObjectsLength; i++) { - if (objectID == sceneObjects[i].id) - { - // Sphere - if (sceneObjects[i].objectType == SceneObjectTypeSphere) { - normal = sphereNormal(pos, sceneObjects[i]); - } - // Plane - if (sceneObjects[i].objectType == SceneObjectTypePlane) { - normal = sceneObjects[i].objectProperties.xyz; - } - // Lighting - float diffuse = lightDiffuse(normal, lightVec); - float specular = lightSpecular(normal, lightVec, sceneObjects[i].specular); - color = diffuse * sceneObjects[i].diffuse + specular; - } - } - - if (id == -1) - return color; - - id = objectID; - - // Shadows - t = length(ubo.lightPos - pos); - color *= calcShadow(pos, lightVec, id, t); - - // Fog - color = fog(t, color); - - // Reflect ray for next render pass - reflectRay(rayD, normal); - rayO = pos; - - return color; -} - -[numthreads(16, 16, 1)] -void main(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - int2 dim; - resultImage.GetDimensions(dim.x, dim.y); - float2 uv = float2(GlobalInvocationID.xy) / dim; - - float3 rayO = ubo.camera.pos; - float3 rayD = normalize(float3((-1.0 + 2.0 * uv) * float2(ubo.aspectRatio, 1.0), -1.0)); - - // Basic color path - int id = 0; - float3 finalColor = renderScene(rayO, rayD, id); - - // Reflection - if (REFLECTIONS) - { - float reflectionStrength = REFLECTIONSTRENGTH; - for (int i = 0; i < RAYBOUNCES; i++) - { - float3 reflectionColor = renderScene(rayO, rayD, id); - finalColor = (1.0 - reflectionStrength) * finalColor + reflectionStrength * lerp(reflectionColor, finalColor, 1.0 - reflectionStrength); - reflectionStrength *= REFLECTIONFALLOFF; - } - } - - resultImage[int2(GlobalInvocationID.xy)] = float4(finalColor, 0.0); -} \ No newline at end of file diff --git a/shaders/hlsl/computeraytracing/raytracing.comp.spv b/shaders/hlsl/computeraytracing/raytracing.comp.spv deleted file mode 100644 index ed2571b6..00000000 Binary files a/shaders/hlsl/computeraytracing/raytracing.comp.spv and /dev/null differ diff --git a/shaders/hlsl/computeraytracing/texture.frag b/shaders/hlsl/computeraytracing/texture.frag deleted file mode 100644 index 99e548ad..00000000 --- a/shaders/hlsl/computeraytracing/texture.frag +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t0); -SamplerState samplerColor : register(s0); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - return textureColor.Sample(samplerColor, float2(inUV.x, 1.0 - inUV.y)); -} \ No newline at end of file diff --git a/shaders/hlsl/computeraytracing/texture.frag.spv b/shaders/hlsl/computeraytracing/texture.frag.spv deleted file mode 100644 index 51a84248..00000000 Binary files a/shaders/hlsl/computeraytracing/texture.frag.spv and /dev/null differ diff --git a/shaders/hlsl/computeraytracing/texture.vert b/shaders/hlsl/computeraytracing/texture.vert deleted file mode 100644 index 36d824cb..00000000 --- a/shaders/hlsl/computeraytracing/texture.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f + -1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/computeraytracing/texture.vert.spv b/shaders/hlsl/computeraytracing/texture.vert.spv deleted file mode 100644 index d9bb5ce5..00000000 Binary files a/shaders/hlsl/computeraytracing/texture.vert.spv and /dev/null differ diff --git a/shaders/hlsl/computeshader/edgedetect.comp b/shaders/hlsl/computeshader/edgedetect.comp deleted file mode 100644 index f3e0d425..00000000 --- a/shaders/hlsl/computeshader/edgedetect.comp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D inputImage : register(t0); -RWTexture2D resultImage : register(u1); - -float conv(float kernel[9], in float data[9], in float denom, in float offset) -{ - float res = 0.0; - for (int i=0; i<9; ++i) - { - res += kernel[i] * data[i]; - } - return saturate(res/denom + offset); -} - -[numthreads(16, 16, 1)] -void main(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - float imageData[9]; - // Fetch neighbouring texels - int n = -1; - for (int i=-1; i<2; ++i) - { - for(int j=-1; j<2; ++j) - { - n++; - float3 rgb = inputImage[uint2(GlobalInvocationID.x + i, GlobalInvocationID.y + j)].rgb; - imageData[n] = (rgb.r + rgb.g + rgb.b) / 3.0; - } - } - - float kernel[9]; - kernel[0] = -1.0/8.0; kernel[1] = -1.0/8.0; kernel[2] = -1.0/8.0; - kernel[3] = -1.0/8.0; kernel[4] = 1.0; kernel[5] = -1.0/8.0; - kernel[6] = -1.0/8.0; kernel[7] = -1.0/8.0; kernel[8] = -1.0/8.0; - - float4 res = float4(conv(kernel, imageData, 0.1, 0.0).xxx, 1.0); - - resultImage[int2(GlobalInvocationID.xy)] = res; -} diff --git a/shaders/hlsl/computeshader/edgedetect.comp.spv b/shaders/hlsl/computeshader/edgedetect.comp.spv deleted file mode 100644 index f06a054b..00000000 Binary files a/shaders/hlsl/computeshader/edgedetect.comp.spv and /dev/null differ diff --git a/shaders/hlsl/computeshader/emboss.comp b/shaders/hlsl/computeshader/emboss.comp deleted file mode 100644 index f2a07027..00000000 --- a/shaders/hlsl/computeshader/emboss.comp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D inputImage : register(t0); -RWTexture2D resultImage : register(u1); - -float conv(in float kernel[9], in float data[9], in float denom, in float offset) -{ - float res = 0.0; - for (int i=0; i<9; ++i) - { - res += kernel[i] * data[i]; - } - return saturate(res/denom + offset); -} - -[numthreads(16, 16, 1)] -void main(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - float imageData[9]; - // Fetch neighbouring texels - int n = -1; - for (int i=-1; i<2; ++i) - { - for(int j=-1; j<2; ++j) - { - n++; - float3 rgb = inputImage[uint2(GlobalInvocationID.x + i, GlobalInvocationID.y + j)].rgb; - imageData[n] = (rgb.r + rgb.g + rgb.b) / 3.0; - } - } - - float kernel[9]; - kernel[0] = -1.0; kernel[1] = 0.0; kernel[2] = 0.0; - kernel[3] = 0.0; kernel[4] = -1.0; kernel[5] = 0.0; - kernel[6] = 0.0; kernel[7] = 0.0; kernel[8] = 2.0; - - float4 res = float4(conv(kernel, imageData, 1.0, 0.50).xxx, 1.0); - - resultImage[int2(GlobalInvocationID.xy)] = res; -} \ No newline at end of file diff --git a/shaders/hlsl/computeshader/emboss.comp.spv b/shaders/hlsl/computeshader/emboss.comp.spv deleted file mode 100644 index 98a666b4..00000000 Binary files a/shaders/hlsl/computeshader/emboss.comp.spv and /dev/null differ diff --git a/shaders/hlsl/computeshader/sharpen.comp b/shaders/hlsl/computeshader/sharpen.comp deleted file mode 100644 index 90a58266..00000000 --- a/shaders/hlsl/computeshader/sharpen.comp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D inputImage : register(t0); -RWTexture2D resultImage : register(u1); - -float conv(in float kernel[9], in float data[9], in float denom, in float offset) -{ - float res = 0.0; - for (int i=0; i<9; ++i) - { - res += kernel[i] * data[i]; - } - return saturate(res/denom + offset); -} - -[numthreads(16, 16, 1)] -void main(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - float r[9]; - float g[9]; - float b[9]; - - // Fetch neighbouring texels - int n = -1; - for (int i=-1; i<2; ++i) - { - for(int j=-1; j<2; ++j) - { - n++; - float3 rgb = inputImage[uint2(GlobalInvocationID.x + i, GlobalInvocationID.y + j)].rgb; - r[n] = rgb.r; - g[n] = rgb.g; - b[n] = rgb.b; - } - } - - float kernel[9]; - kernel[0] = -1.0; kernel[1] = -1.0; kernel[2] = -1.0; - kernel[3] = -1.0; kernel[4] = 9.0; kernel[5] = -1.0; - kernel[6] = -1.0; kernel[7] = -1.0; kernel[8] = -1.0; - - float4 res = float4( - conv(kernel, r, 1.0, 0.0), - conv(kernel, g, 1.0, 0.0), - conv(kernel, b, 1.0, 0.0), - 1.0); - - resultImage[int2(GlobalInvocationID.xy)] = res; -} \ No newline at end of file diff --git a/shaders/hlsl/computeshader/sharpen.comp.spv b/shaders/hlsl/computeshader/sharpen.comp.spv deleted file mode 100644 index b3b013cd..00000000 Binary files a/shaders/hlsl/computeshader/sharpen.comp.spv and /dev/null differ diff --git a/shaders/hlsl/computeshader/texture.frag b/shaders/hlsl/computeshader/texture.frag deleted file mode 100644 index 997a9419..00000000 --- a/shaders/hlsl/computeshader/texture.frag +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - return textureColor.Sample(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/hlsl/computeshader/texture.frag.spv b/shaders/hlsl/computeshader/texture.frag.spv deleted file mode 100644 index 5a671efa..00000000 Binary files a/shaders/hlsl/computeshader/texture.frag.spv and /dev/null differ diff --git a/shaders/hlsl/computeshader/texture.vert b/shaders/hlsl/computeshader/texture.vert deleted file mode 100644 index 8021fe95..00000000 --- a/shaders/hlsl/computeshader/texture.vert +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; - [[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} diff --git a/shaders/hlsl/computeshader/texture.vert.spv b/shaders/hlsl/computeshader/texture.vert.spv deleted file mode 100644 index 5b4eecdc..00000000 Binary files a/shaders/hlsl/computeshader/texture.vert.spv and /dev/null differ diff --git a/shaders/hlsl/conditionalrender/model.frag b/shaders/hlsl/conditionalrender/model.frag deleted file mode 100644 index 2c14be89..00000000 --- a/shaders/hlsl/conditionalrender/model.frag +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.1, 0.1, 0.1); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/conditionalrender/model.frag.spv b/shaders/hlsl/conditionalrender/model.frag.spv deleted file mode 100644 index 6966e9ad..00000000 Binary files a/shaders/hlsl/conditionalrender/model.frag.spv and /dev/null differ diff --git a/shaders/hlsl/conditionalrender/model.vert b/shaders/hlsl/conditionalrender/model.vert deleted file mode 100644 index 929321e1..00000000 --- a/shaders/hlsl/conditionalrender/model.vert +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct Node -{ - float4x4 transform; -}; - -cbuffer NodeBuf : register(b0, space1) { Node node; } - -struct PushConstant -{ - float4 baseColorFactor; -}; - -[[vk::push_constant]] PushConstant material; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = material.baseColorFactor.rgb; - float4 pos = float4(input.Pos, 1.0); - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, mul(node.transform, pos)))); - - output.Normal = mul((float4x3)mul(ubo.view, mul(ubo.model, node.transform)), input.Normal).xyz; - - float4 localpos = mul(ubo.view, mul(ubo.model, mul(node.transform, pos))); - float3 lightPos = float3(10.0f, -10.0f, 10.0f); - output.LightVec = lightPos.xyz - localpos.xyz; - output.ViewVec = -localpos.xyz; - return output; -} diff --git a/shaders/hlsl/conditionalrender/model.vert.spv b/shaders/hlsl/conditionalrender/model.vert.spv deleted file mode 100644 index b64747cc..00000000 Binary files a/shaders/hlsl/conditionalrender/model.vert.spv and /dev/null differ diff --git a/shaders/hlsl/conservativeraster/fullscreen.frag b/shaders/hlsl/conservativeraster/fullscreen.frag deleted file mode 100644 index 661ddf44..00000000 --- a/shaders/hlsl/conservativeraster/fullscreen.frag +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - return textureColor.Sample(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/hlsl/conservativeraster/fullscreen.frag.spv b/shaders/hlsl/conservativeraster/fullscreen.frag.spv deleted file mode 100644 index 5a671efa..00000000 Binary files a/shaders/hlsl/conservativeraster/fullscreen.frag.spv and /dev/null differ diff --git a/shaders/hlsl/conservativeraster/fullscreen.vert b/shaders/hlsl/conservativeraster/fullscreen.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/conservativeraster/fullscreen.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/conservativeraster/fullscreen.vert.spv b/shaders/hlsl/conservativeraster/fullscreen.vert.spv deleted file mode 100644 index 46c4b31f..00000000 Binary files a/shaders/hlsl/conservativeraster/fullscreen.vert.spv and /dev/null differ diff --git a/shaders/hlsl/conservativeraster/triangle.frag b/shaders/hlsl/conservativeraster/triangle.frag deleted file mode 100644 index 2387dd14..00000000 --- a/shaders/hlsl/conservativeraster/triangle.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main([[vk::location(0)]] float3 Color : COLOR0) : SV_TARGET -{ - return float4(Color, 1); -} \ No newline at end of file diff --git a/shaders/hlsl/conservativeraster/triangle.frag.spv b/shaders/hlsl/conservativeraster/triangle.frag.spv deleted file mode 100644 index 870fb6c1..00000000 Binary files a/shaders/hlsl/conservativeraster/triangle.frag.spv and /dev/null differ diff --git a/shaders/hlsl/conservativeraster/triangle.vert b/shaders/hlsl/conservativeraster/triangle.vert deleted file mode 100644 index e7c529be..00000000 --- a/shaders/hlsl/conservativeraster/triangle.vert +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos, 1.0))); - return output; -} diff --git a/shaders/hlsl/conservativeraster/triangle.vert.spv b/shaders/hlsl/conservativeraster/triangle.vert.spv deleted file mode 100644 index 66b032f9..00000000 Binary files a/shaders/hlsl/conservativeraster/triangle.vert.spv and /dev/null differ diff --git a/shaders/hlsl/conservativeraster/triangleoverlay.frag b/shaders/hlsl/conservativeraster/triangleoverlay.frag deleted file mode 100644 index 9892e709..00000000 --- a/shaders/hlsl/conservativeraster/triangleoverlay.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main() : SV_TARGET -{ - return float4(1.0, 1.0, 1.0, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/conservativeraster/triangleoverlay.frag.spv b/shaders/hlsl/conservativeraster/triangleoverlay.frag.spv deleted file mode 100644 index da33b821..00000000 Binary files a/shaders/hlsl/conservativeraster/triangleoverlay.frag.spv and /dev/null differ diff --git a/shaders/hlsl/debugprintf/toon.frag b/shaders/hlsl/debugprintf/toon.frag deleted file mode 100644 index ef1637df..00000000 --- a/shaders/hlsl/debugprintf/toon.frag +++ /dev/null @@ -1,34 +0,0 @@ -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - // Desaturate color - float3 color = float3(lerp(input.Color, dot(float3(0.2126,0.7152,0.0722), input.Color).xxx, 0.65)); - - // High ambient colors because mesh materials are pretty dark - float3 ambient = color * float3(1.0, 1.0, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - - float intensity = dot(N,L); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - return float4(input.Color * 3.0 * shade, 1); -} \ No newline at end of file diff --git a/shaders/hlsl/debugprintf/toon.frag.spv b/shaders/hlsl/debugprintf/toon.frag.spv deleted file mode 100644 index 630d3ba4..00000000 Binary files a/shaders/hlsl/debugprintf/toon.frag.spv and /dev/null differ diff --git a/shaders/hlsl/debugprintf/toon.vert b/shaders/hlsl/debugprintf/toon.vert deleted file mode 100644 index 65b5a4ce..00000000 --- a/shaders/hlsl/debugprintf/toon.vert +++ /dev/null @@ -1,42 +0,0 @@ -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - // Output the vertex position using debug printf - printf("Position = %v4f", pos); - - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - float3 lPos = mul((float4x3)ubo.model, ubo.lightPos.xyz).xyz; - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/debugprintf/toon.vert.spv b/shaders/hlsl/debugprintf/toon.vert.spv deleted file mode 100644 index e061231e..00000000 Binary files a/shaders/hlsl/debugprintf/toon.vert.spv and /dev/null differ diff --git a/shaders/hlsl/debugutils/colorpass.frag b/shaders/hlsl/debugutils/colorpass.frag deleted file mode 100644 index 2387dd14..00000000 --- a/shaders/hlsl/debugutils/colorpass.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main([[vk::location(0)]] float3 Color : COLOR0) : SV_TARGET -{ - return float4(Color, 1); -} \ No newline at end of file diff --git a/shaders/hlsl/debugutils/colorpass.frag.spv b/shaders/hlsl/debugutils/colorpass.frag.spv deleted file mode 100644 index 870fb6c1..00000000 Binary files a/shaders/hlsl/debugutils/colorpass.frag.spv and /dev/null differ diff --git a/shaders/hlsl/debugutils/colorpass.vert b/shaders/hlsl/debugutils/colorpass.vert deleted file mode 100644 index 089cd426..00000000 --- a/shaders/hlsl/debugutils/colorpass.vert +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, input.Pos)); - return output; -} diff --git a/shaders/hlsl/debugutils/colorpass.vert.spv b/shaders/hlsl/debugutils/colorpass.vert.spv deleted file mode 100644 index cde88b5f..00000000 Binary files a/shaders/hlsl/debugutils/colorpass.vert.spv and /dev/null differ diff --git a/shaders/hlsl/debugutils/postprocess.frag b/shaders/hlsl/debugutils/postprocess.frag deleted file mode 100644 index 32bef01b..00000000 --- a/shaders/hlsl/debugutils/postprocess.frag +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - // Single pass gauss blur - - const float2 texOffset = float2(0.01, 0.01); - - float2 tc0 = inUV + float2(-texOffset.x, -texOffset.y); - float2 tc1 = inUV + float2( 0.0, -texOffset.y); - float2 tc2 = inUV + float2(+texOffset.x, -texOffset.y); - float2 tc3 = inUV + float2(-texOffset.x, 0.0); - float2 tc4 = inUV + float2( 0.0, 0.0); - float2 tc5 = inUV + float2(+texOffset.x, 0.0); - float2 tc6 = inUV + float2(-texOffset.x, +texOffset.y); - float2 tc7 = inUV + float2( 0.0, +texOffset.y); - float2 tc8 = inUV + float2(+texOffset.x, +texOffset.y); - - float4 col0 = textureColor.Sample(samplerColor, tc0); - float4 col1 = textureColor.Sample(samplerColor, tc1); - float4 col2 = textureColor.Sample(samplerColor, tc2); - float4 col3 = textureColor.Sample(samplerColor, tc3); - float4 col4 = textureColor.Sample(samplerColor, tc4); - float4 col5 = textureColor.Sample(samplerColor, tc5); - float4 col6 = textureColor.Sample(samplerColor, tc6); - float4 col7 = textureColor.Sample(samplerColor, tc7); - float4 col8 = textureColor.Sample(samplerColor, tc8); - - float4 sum = (1.0 * col0 + 2.0 * col1 + 1.0 * col2 + - 2.0 * col3 + 4.0 * col4 + 2.0 * col5 + - 1.0 * col6 + 2.0 * col7 + 1.0 * col8) / 16.0; - return float4(sum.rgb, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/debugutils/postprocess.frag.spv b/shaders/hlsl/debugutils/postprocess.frag.spv deleted file mode 100644 index 7a15cf74..00000000 Binary files a/shaders/hlsl/debugutils/postprocess.frag.spv and /dev/null differ diff --git a/shaders/hlsl/debugutils/postprocess.vert b/shaders/hlsl/debugutils/postprocess.vert deleted file mode 100644 index fca6ef51..00000000 --- a/shaders/hlsl/debugutils/postprocess.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * float2(2.0f, 2.0f) + float2(-1.0f, -1.0f), 0.0f, 1.0f); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/debugutils/postprocess.vert.spv b/shaders/hlsl/debugutils/postprocess.vert.spv deleted file mode 100644 index e17bb016..00000000 Binary files a/shaders/hlsl/debugutils/postprocess.vert.spv and /dev/null differ diff --git a/shaders/hlsl/debugutils/toon.frag b/shaders/hlsl/debugutils/toon.frag deleted file mode 100644 index fa2e7a35..00000000 --- a/shaders/hlsl/debugutils/toon.frag +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - // Desaturate color - float3 color = float3(lerp(input.Color, dot(float3(0.2126,0.7152,0.0722), input.Color).xxx, 0.65)); - - // High ambient colors because mesh materials are pretty dark - float3 ambient = color * float3(1.0, 1.0, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - - float intensity = dot(N,L); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - return float4(input.Color * 3.0 * shade, 1); -} \ No newline at end of file diff --git a/shaders/hlsl/debugutils/toon.frag.spv b/shaders/hlsl/debugutils/toon.frag.spv deleted file mode 100644 index 168f5b63..00000000 Binary files a/shaders/hlsl/debugutils/toon.frag.spv and /dev/null differ diff --git a/shaders/hlsl/debugutils/toon.vert b/shaders/hlsl/debugutils/toon.vert deleted file mode 100644 index 3755608d..00000000 --- a/shaders/hlsl/debugutils/toon.vert +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - float3 lPos = mul((float4x3)ubo.model, ubo.lightPos.xyz).xyz; - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/debugutils/toon.vert.spv b/shaders/hlsl/debugutils/toon.vert.spv deleted file mode 100644 index c06a7e59..00000000 Binary files a/shaders/hlsl/debugutils/toon.vert.spv and /dev/null differ diff --git a/shaders/hlsl/deferred/deferred.frag b/shaders/hlsl/deferred/deferred.frag deleted file mode 100644 index fbcaab67..00000000 --- a/shaders/hlsl/deferred/deferred.frag +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureposition : register(t1); -SamplerState samplerposition : register(s1); -Texture2D textureNormal : register(t2); -SamplerState samplerNormal : register(s2); -Texture2D textureAlbedo : register(t3); -SamplerState samplerAlbedo : register(s3); - -struct Light { - float4 position; - float3 color; - float radius; -}; - -struct UBO -{ - Light lights[6]; - float4 viewPos; - int displayDebugTarget; -}; - -cbuffer ubo : register(b4) { UBO ubo; } - - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - // Get G-Buffer values - float3 fragPos = textureposition.Sample(samplerposition, inUV).rgb; - float3 normal = textureNormal.Sample(samplerNormal, inUV).rgb; - float4 albedo = textureAlbedo.Sample(samplerAlbedo, inUV); - - float3 fragcolor; - - // Debug display - if (ubo.displayDebugTarget > 0) { - switch (ubo.displayDebugTarget) { - case 1: - fragcolor.rgb = fragPos; - break; - case 2: - fragcolor.rgb = normal; - break; - case 3: - fragcolor.rgb = albedo.rgb; - break; - case 4: - fragcolor.rgb = albedo.aaa; - break; - } - return float4(fragcolor, 1.0); - } - - #define lightCount 6 - #define ambient 0.0 - - // Ambient part - fragcolor = albedo.rgb * ambient; - - for(int i = 0; i < lightCount; ++i) - { - // Vector to light - float3 L = ubo.lights[i].position.xyz - fragPos; - // Distance from light to fragment position - float dist = length(L); - - // Viewer to fragment - float3 V = ubo.viewPos.xyz - fragPos; - V = normalize(V); - - //if(dist < ubo.lights[i].radius) - { - // Light to fragment - L = normalize(L); - - // Attenuation - float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0); - - // Diffuse part - float3 N = normalize(normal); - float NdotL = max(0.0, dot(N, L)); - float3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten; - - // Specular part - // Specular map values are stored in alpha of albedo mrt - float3 R = reflect(-L, N); - float NdotR = max(0.0, dot(R, V)); - float3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 16.0) * atten; - - fragcolor += diff + spec; - } - } - - return float4(fragcolor, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/deferred/deferred.frag.spv b/shaders/hlsl/deferred/deferred.frag.spv deleted file mode 100644 index cbaceb91..00000000 Binary files a/shaders/hlsl/deferred/deferred.frag.spv and /dev/null differ diff --git a/shaders/hlsl/deferred/deferred.vert b/shaders/hlsl/deferred/deferred.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/deferred/deferred.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/deferred/deferred.vert.spv b/shaders/hlsl/deferred/deferred.vert.spv deleted file mode 100644 index 8754eaa1..00000000 Binary files a/shaders/hlsl/deferred/deferred.vert.spv and /dev/null differ diff --git a/shaders/hlsl/deferred/mrt.frag b/shaders/hlsl/deferred/mrt.frag deleted file mode 100644 index 7b899821..00000000 --- a/shaders/hlsl/deferred/mrt.frag +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); -Texture2D textureNormalMap : register(t2); -SamplerState samplerNormalMap : register(s2); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 WorldPos : POSITION0; -[[vk::location(4)]] float3 Tangent : TEXCOORD1; -}; - -struct FSOutput -{ - float4 Position : SV_TARGET0; - float4 Normal : SV_TARGET1; - float4 Albedo : SV_TARGET2; -}; - -FSOutput main(VSOutput input) -{ - FSOutput output = (FSOutput)0; - output.Position = float4(input.WorldPos, 1.0); - - // Calculate normal in tangent space - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent); - float3 B = cross(N, T); - float3x3 TBN = float3x3(T, B, N); - float3 tnorm = mul(normalize(textureNormalMap.Sample(samplerNormalMap, input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - output.Normal = float4(tnorm, 1.0); - - output.Albedo = textureColor.Sample(samplerColor, input.UV); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/deferred/mrt.frag.spv b/shaders/hlsl/deferred/mrt.frag.spv deleted file mode 100644 index a2085df9..00000000 Binary files a/shaders/hlsl/deferred/mrt.frag.spv and /dev/null differ diff --git a/shaders/hlsl/deferred/mrt.vert b/shaders/hlsl/deferred/mrt.vert deleted file mode 100644 index 35254573..00000000 --- a/shaders/hlsl/deferred/mrt.vert +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 Normal : NORMAL0; -[[vk::location(4)]] float3 Tangent : TEXCOORD1; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float4 instancePos[3]; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 WorldPos : POSITION0; -[[vk::location(4)]] float3 Tangent : TEXCOORD1; -}; - -VSOutput main(VSInput input, uint InstanceIndex : SV_InstanceID) -{ - VSOutput output = (VSOutput)0; - float4 tmpPos = input.Pos + ubo.instancePos[InstanceIndex]; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, tmpPos))); - - output.UV = input.UV; - - // Vertex position in world space - output.WorldPos = mul(ubo.model, tmpPos).xyz; - - // Normal in world space - output.Normal = normalize(input.Normal); - output.Tangent = normalize(input.Tangent); - - // Currently just vertex color - output.Color = input.Color; - return output; -} diff --git a/shaders/hlsl/deferred/mrt.vert.spv b/shaders/hlsl/deferred/mrt.vert.spv deleted file mode 100644 index 31f2eafb..00000000 Binary files a/shaders/hlsl/deferred/mrt.vert.spv and /dev/null differ diff --git a/shaders/hlsl/deferredmultisampling/deferred.frag b/shaders/hlsl/deferredmultisampling/deferred.frag deleted file mode 100644 index ea1081c9..00000000 --- a/shaders/hlsl/deferredmultisampling/deferred.frag +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2DMS texturePosition : register(t1); -SamplerState samplerPosition : register(s1); -Texture2DMS textureNormal : register(t2); -SamplerState samplerNormal : register(s2); -Texture2DMS textureAlbedo : register(t3); -SamplerState samplerAlbedo : register(s3); - -struct Light { - float4 position; - float3 color; - float radius; -}; - -struct UBO -{ - Light lights[6]; - float4 viewPos; - int debugDisplayTarget; -}; - -cbuffer ubo : register(b4) { UBO ubo; } - -[[vk::constant_id(0)]] const int NUM_SAMPLES = 8; - -#define NUM_LIGHTS 6 - -// Manual resolve for MSAA samples -float4 resolve(Texture2DMS tex, int2 uv) -{ - float4 result = float4(0.0, 0.0, 0.0, 0.0); - for (int i = 0; i < NUM_SAMPLES; i++) - { - uint status = 0; - float4 val = tex.Load(uv, i, int2(0, 0), status); - result += val; - } - // Average resolved samples - return result / float(NUM_SAMPLES); -} - -float3 calculateLighting(float3 pos, float3 normal, float4 albedo) -{ - float3 result = float3(0.0, 0.0, 0.0); - - for(int i = 0; i < NUM_LIGHTS; ++i) - { - // Vector to light - float3 L = ubo.lights[i].position.xyz - pos; - // Distance from light to fragment position - float dist = length(L); - - // Viewer to fragment - float3 V = ubo.viewPos.xyz - pos; - V = normalize(V); - - // Light to fragment - L = normalize(L); - - // Attenuation - float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0); - - // Diffuse part - float3 N = normalize(normal); - float NdotL = max(0.0, dot(N, L)); - float3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten; - - // Specular part - float3 R = reflect(-L, N); - float NdotR = max(0.0, dot(R, V)); - float3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 8.0) * atten; - - result += diff + spec; - } - return result; -} - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - int2 attDim; int sampleCount; - texturePosition.GetDimensions(attDim.x, attDim.y, sampleCount); - int2 UV = int2(inUV * attDim); - - float3 fragColor; - uint status = 0; - - // Debug display - if (ubo.debugDisplayTarget > 0) { - switch (ubo.debugDisplayTarget) { - case 1: - fragColor.rgb = texturePosition.Load(UV, 0, int2(0, 0), status).rgb; - break; - case 2: - fragColor.rgb = textureNormal.Load(UV, 0, int2(0, 0), status).rgb; - break; - case 3: - fragColor.rgb = textureAlbedo.Load(UV, 0, int2(0, 0), status).rgb; - break; - case 4: - fragColor.rgb = textureAlbedo.Load(UV, 0, int2(0, 0), status).aaa; - break; - } - return float4(fragColor, 1.0); - } - - #define ambient 0.15 - - // Ambient part - float4 alb = resolve(textureAlbedo, UV); - fragColor = float3(0.0, 0.0, 0.0); - - // Calualte lighting for every MSAA sample - for (int i = 0; i < NUM_SAMPLES; i++) - { - float3 pos = texturePosition.Load(UV, i, int2(0, 0), status).rgb; - float3 normal = textureNormal.Load(UV, i, int2(0, 0), status).rgb; - float4 albedo = textureAlbedo.Load(UV, i, int2(0, 0), status); - fragColor += calculateLighting(pos, normal, albedo); - } - - fragColor = (alb.rgb * ambient) + fragColor / float(NUM_SAMPLES); - - return float4(fragColor, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/deferredmultisampling/deferred.frag.spv b/shaders/hlsl/deferredmultisampling/deferred.frag.spv deleted file mode 100644 index 253f0e11..00000000 Binary files a/shaders/hlsl/deferredmultisampling/deferred.frag.spv and /dev/null differ diff --git a/shaders/hlsl/deferredmultisampling/deferred.vert b/shaders/hlsl/deferredmultisampling/deferred.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/deferredmultisampling/deferred.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/deferredmultisampling/deferred.vert.spv b/shaders/hlsl/deferredmultisampling/deferred.vert.spv deleted file mode 100644 index 8754eaa1..00000000 Binary files a/shaders/hlsl/deferredmultisampling/deferred.vert.spv and /dev/null differ diff --git a/shaders/hlsl/deferredmultisampling/mrt.frag b/shaders/hlsl/deferredmultisampling/mrt.frag deleted file mode 100644 index 7b899821..00000000 --- a/shaders/hlsl/deferredmultisampling/mrt.frag +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); -Texture2D textureNormalMap : register(t2); -SamplerState samplerNormalMap : register(s2); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 WorldPos : POSITION0; -[[vk::location(4)]] float3 Tangent : TEXCOORD1; -}; - -struct FSOutput -{ - float4 Position : SV_TARGET0; - float4 Normal : SV_TARGET1; - float4 Albedo : SV_TARGET2; -}; - -FSOutput main(VSOutput input) -{ - FSOutput output = (FSOutput)0; - output.Position = float4(input.WorldPos, 1.0); - - // Calculate normal in tangent space - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent); - float3 B = cross(N, T); - float3x3 TBN = float3x3(T, B, N); - float3 tnorm = mul(normalize(textureNormalMap.Sample(samplerNormalMap, input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - output.Normal = float4(tnorm, 1.0); - - output.Albedo = textureColor.Sample(samplerColor, input.UV); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/deferredmultisampling/mrt.frag.spv b/shaders/hlsl/deferredmultisampling/mrt.frag.spv deleted file mode 100644 index a2085df9..00000000 Binary files a/shaders/hlsl/deferredmultisampling/mrt.frag.spv and /dev/null differ diff --git a/shaders/hlsl/deferredmultisampling/mrt.vert b/shaders/hlsl/deferredmultisampling/mrt.vert deleted file mode 100644 index 35254573..00000000 --- a/shaders/hlsl/deferredmultisampling/mrt.vert +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 Normal : NORMAL0; -[[vk::location(4)]] float3 Tangent : TEXCOORD1; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float4 instancePos[3]; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 WorldPos : POSITION0; -[[vk::location(4)]] float3 Tangent : TEXCOORD1; -}; - -VSOutput main(VSInput input, uint InstanceIndex : SV_InstanceID) -{ - VSOutput output = (VSOutput)0; - float4 tmpPos = input.Pos + ubo.instancePos[InstanceIndex]; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, tmpPos))); - - output.UV = input.UV; - - // Vertex position in world space - output.WorldPos = mul(ubo.model, tmpPos).xyz; - - // Normal in world space - output.Normal = normalize(input.Normal); - output.Tangent = normalize(input.Tangent); - - // Currently just vertex color - output.Color = input.Color; - return output; -} diff --git a/shaders/hlsl/deferredmultisampling/mrt.vert.spv b/shaders/hlsl/deferredmultisampling/mrt.vert.spv deleted file mode 100644 index 31f2eafb..00000000 Binary files a/shaders/hlsl/deferredmultisampling/mrt.vert.spv and /dev/null differ diff --git a/shaders/hlsl/deferredshadows/deferred.frag b/shaders/hlsl/deferredshadows/deferred.frag deleted file mode 100644 index 4ef651cc..00000000 --- a/shaders/hlsl/deferredshadows/deferred.frag +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureposition : register(t1); -SamplerState samplerposition : register(s1); -Texture2D textureNormal : register(t2); -SamplerState samplerNormal : register(s2); -Texture2D textureAlbedo : register(t3); -SamplerState samplerAlbedo : register(s3); -// Depth from the light's point of view -//layout (binding = 5) uniform sampler2DShadow samplerShadowMap; -Texture2DArray textureShadowMap : register(t5); -SamplerState samplerShadowMap : register(s5); - -#define LIGHT_COUNT 3 -#define SHADOW_FACTOR 0.25 -#define AMBIENT_LIGHT 0.1 -#define USE_PCF - -struct Light -{ - float4 position; - float4 target; - float4 color; - float4x4 viewMatrix; -}; - -struct UBO -{ - float4 viewPos; - Light lights[LIGHT_COUNT]; - int useShadows; - int displayDebugTarget; -}; - -cbuffer ubo : register(b4) { UBO ubo; } - -float textureProj(float4 P, float layer, float2 offset) -{ - float shadow = 1.0; - float4 shadowCoord = P / P.w; - shadowCoord.xy = shadowCoord.xy * 0.5 + 0.5; - - if (shadowCoord.z > -1.0 && shadowCoord.z < 1.0) - { - float dist = textureShadowMap.Sample(samplerShadowMap, float3(shadowCoord.xy + offset, layer)).r; - if (shadowCoord.w > 0.0 && dist < shadowCoord.z) - { - shadow = SHADOW_FACTOR; - } - } - return shadow; -} - -float filterPCF(float4 sc, float layer) -{ - int2 texDim; int elements; int levels; - textureShadowMap.GetDimensions(0, texDim.x, texDim.y, elements, levels); - float scale = 1.5; - float dx = scale * 1.0 / float(texDim.x); - float dy = scale * 1.0 / float(texDim.y); - - float shadowFactor = 0.0; - int count = 0; - int range = 1; - - for (int x = -range; x <= range; x++) - { - for (int y = -range; y <= range; y++) - { - shadowFactor += textureProj(sc, layer, float2(dx*x, dy*y)); - count++; - } - - } - return shadowFactor / count; -} - -float3 shadow(float3 fragcolor, float3 fragPos) { - for (int i = 0; i < LIGHT_COUNT; ++i) - { - float4 shadowClip = mul(ubo.lights[i].viewMatrix, float4(fragPos.xyz, 1.0)); - - float shadowFactor; - #ifdef USE_PCF - shadowFactor= filterPCF(shadowClip, i); - #else - shadowFactor = textureProj(shadowClip, i, float2(0.0, 0.0)); - #endif - - fragcolor *= shadowFactor; - } - return fragcolor; -} - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - // Get G-Buffer values - float3 fragPos = textureposition.Sample(samplerposition, inUV).rgb; - float3 normal = textureNormal.Sample(samplerNormal, inUV).rgb; - float4 albedo = textureAlbedo.Sample(samplerAlbedo, inUV); - - float3 fragcolor; - - // Debug display - if (ubo.displayDebugTarget > 0) { - switch (ubo.displayDebugTarget) { - case 1: - fragcolor.rgb = shadow(float3(1.0, 1.0, 1.0), fragPos); - break; - case 2: - fragcolor.rgb = fragPos; - break; - case 3: - fragcolor.rgb = normal; - break; - case 4: - fragcolor.rgb = albedo.rgb; - break; - case 5: - fragcolor.rgb = albedo.aaa; - break; - } - return float4(fragcolor, 1.0); - } - - // Ambient part - fragcolor = albedo.rgb * AMBIENT_LIGHT; - - float3 N = normalize(normal); - - for(int i = 0; i < LIGHT_COUNT; ++i) - { - // Vector to light - float3 L = ubo.lights[i].position.xyz - fragPos; - // Distance from light to fragment position - float dist = length(L); - L = normalize(L); - - // Viewer to fragment - float3 V = ubo.viewPos.xyz - fragPos; - V = normalize(V); - - float lightCosInnerAngle = cos(radians(15.0)); - float lightCosOuterAngle = cos(radians(25.0)); - float lightRange = 100.0; - - // Direction vector from source to target - float3 dir = normalize(ubo.lights[i].position.xyz - ubo.lights[i].target.xyz); - - // Dual cone spot light with smooth transition between inner and outer angle - float cosDir = dot(L, dir); - float spotEffect = smoothstep(lightCosOuterAngle, lightCosInnerAngle, cosDir); - float heightAttenuation = smoothstep(lightRange, 0.0f, dist); - - // Diffuse lighting - float NdotL = max(0.0, dot(N, L)); - float3 diff = NdotL.xxx; - - // Specular lighting - float3 R = reflect(-L, N); - float NdotR = max(0.0, dot(R, V)); - float3 spec = (pow(NdotR, 16.0) * albedo.a * 2.5).xxx; - - fragcolor += float3((diff + spec) * spotEffect * heightAttenuation) * ubo.lights[i].color.rgb * albedo.rgb; - } - - // Shadow calculations in a separate pass - if (ubo.useShadows > 0) - { - fragcolor = shadow(fragcolor, fragPos); - } - - return float4(fragcolor, 1); -} \ No newline at end of file diff --git a/shaders/hlsl/deferredshadows/deferred.frag.spv b/shaders/hlsl/deferredshadows/deferred.frag.spv deleted file mode 100644 index 79ed9acc..00000000 Binary files a/shaders/hlsl/deferredshadows/deferred.frag.spv and /dev/null differ diff --git a/shaders/hlsl/deferredshadows/deferred.vert b/shaders/hlsl/deferredshadows/deferred.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/deferredshadows/deferred.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/deferredshadows/deferred.vert.spv b/shaders/hlsl/deferredshadows/deferred.vert.spv deleted file mode 100644 index 8754eaa1..00000000 Binary files a/shaders/hlsl/deferredshadows/deferred.vert.spv and /dev/null differ diff --git a/shaders/hlsl/deferredshadows/mrt.frag b/shaders/hlsl/deferredshadows/mrt.frag deleted file mode 100644 index 7b899821..00000000 --- a/shaders/hlsl/deferredshadows/mrt.frag +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); -Texture2D textureNormalMap : register(t2); -SamplerState samplerNormalMap : register(s2); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 WorldPos : POSITION0; -[[vk::location(4)]] float3 Tangent : TEXCOORD1; -}; - -struct FSOutput -{ - float4 Position : SV_TARGET0; - float4 Normal : SV_TARGET1; - float4 Albedo : SV_TARGET2; -}; - -FSOutput main(VSOutput input) -{ - FSOutput output = (FSOutput)0; - output.Position = float4(input.WorldPos, 1.0); - - // Calculate normal in tangent space - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent); - float3 B = cross(N, T); - float3x3 TBN = float3x3(T, B, N); - float3 tnorm = mul(normalize(textureNormalMap.Sample(samplerNormalMap, input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - output.Normal = float4(tnorm, 1.0); - - output.Albedo = textureColor.Sample(samplerColor, input.UV); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/deferredshadows/mrt.frag.spv b/shaders/hlsl/deferredshadows/mrt.frag.spv deleted file mode 100644 index a2085df9..00000000 Binary files a/shaders/hlsl/deferredshadows/mrt.frag.spv and /dev/null differ diff --git a/shaders/hlsl/deferredshadows/mrt.vert b/shaders/hlsl/deferredshadows/mrt.vert deleted file mode 100644 index 35254573..00000000 --- a/shaders/hlsl/deferredshadows/mrt.vert +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 Normal : NORMAL0; -[[vk::location(4)]] float3 Tangent : TEXCOORD1; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float4 instancePos[3]; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 WorldPos : POSITION0; -[[vk::location(4)]] float3 Tangent : TEXCOORD1; -}; - -VSOutput main(VSInput input, uint InstanceIndex : SV_InstanceID) -{ - VSOutput output = (VSOutput)0; - float4 tmpPos = input.Pos + ubo.instancePos[InstanceIndex]; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, tmpPos))); - - output.UV = input.UV; - - // Vertex position in world space - output.WorldPos = mul(ubo.model, tmpPos).xyz; - - // Normal in world space - output.Normal = normalize(input.Normal); - output.Tangent = normalize(input.Tangent); - - // Currently just vertex color - output.Color = input.Color; - return output; -} diff --git a/shaders/hlsl/deferredshadows/mrt.vert.spv b/shaders/hlsl/deferredshadows/mrt.vert.spv deleted file mode 100644 index 31f2eafb..00000000 Binary files a/shaders/hlsl/deferredshadows/mrt.vert.spv and /dev/null differ diff --git a/shaders/hlsl/deferredshadows/shadow.geom b/shaders/hlsl/deferredshadows/shadow.geom deleted file mode 100644 index e8321771..00000000 --- a/shaders/hlsl/deferredshadows/shadow.geom +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 Google LLC - -#define LIGHT_COUNT 3 - -struct UBO -{ - float4x4 mvp[LIGHT_COUNT]; - float4 instancePos[3]; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] int InstanceIndex : TEXCOORD0; -}; - -struct GSOutput -{ - float4 Pos : SV_POSITION; - int Layer : SV_RenderTargetArrayIndex; -}; - -[maxvertexcount(3)] -[instance(3)] -void main(triangle VSOutput input[3], uint InvocationID : SV_GSInstanceID, inout TriangleStream outStream) -{ - float4 instancedPos = ubo.instancePos[input[0].InstanceIndex]; - for (int i = 0; i < 3; i++) - { - float4 tmpPos = input[i].Pos + instancedPos; - GSOutput output = (GSOutput)0; - output.Pos = mul(ubo.mvp[InvocationID], tmpPos); - output.Layer = InvocationID; - outStream.Append( output ); - } - outStream.RestartStrip(); -} \ No newline at end of file diff --git a/shaders/hlsl/deferredshadows/shadow.geom.spv b/shaders/hlsl/deferredshadows/shadow.geom.spv deleted file mode 100644 index 97f85bc9..00000000 Binary files a/shaders/hlsl/deferredshadows/shadow.geom.spv and /dev/null differ diff --git a/shaders/hlsl/deferredshadows/shadow.vert b/shaders/hlsl/deferredshadows/shadow.vert deleted file mode 100644 index f08ec8c7..00000000 --- a/shaders/hlsl/deferredshadows/shadow.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] int InstanceIndex : TEXCOORD0; -}; - -VSOutput main([[vk::location(0)]] float4 Pos : POSITION0, uint InstanceIndex : SV_InstanceID) -{ - VSOutput output = (VSOutput)0; - output.InstanceIndex = InstanceIndex; - output.Pos = Pos; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/deferredshadows/shadow.vert.spv b/shaders/hlsl/deferredshadows/shadow.vert.spv deleted file mode 100644 index 953ea7d5..00000000 Binary files a/shaders/hlsl/deferredshadows/shadow.vert.spv and /dev/null differ diff --git a/shaders/hlsl/descriptorindexing/descriptorindexing.frag b/shaders/hlsl/descriptorindexing/descriptorindexing.frag deleted file mode 100644 index 03a1a0f8..00000000 --- a/shaders/hlsl/descriptorindexing/descriptorindexing.frag +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2021 Sascha Willems -// Non-uniform access is enabled at compile time via SPV_EXT_descriptor_indexing (see compile.py) - -Texture2D textures[] : register(t1); -SamplerState samplerColorMap : register(s1); - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] int TextureIndex : TEXTUREINDEX0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - return textures[NonUniformResourceIndex(input.TextureIndex)].Sample(samplerColorMap, input.UV); -} \ No newline at end of file diff --git a/shaders/hlsl/descriptorindexing/descriptorindexing.frag.spv b/shaders/hlsl/descriptorindexing/descriptorindexing.frag.spv deleted file mode 100644 index e1ef9249..00000000 Binary files a/shaders/hlsl/descriptorindexing/descriptorindexing.frag.spv and /dev/null differ diff --git a/shaders/hlsl/descriptorindexing/descriptorindexing.vert b/shaders/hlsl/descriptorindexing/descriptorindexing.vert deleted file mode 100644 index 74cad39d..00000000 --- a/shaders/hlsl/descriptorindexing/descriptorindexing.vert +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2021 Sascha Willems - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] int TextureIndex : TEXTUREINDEX0; -}; - -struct Matrices { - float4x4 projection; - float4x4 view; - float4x4 model; -}; - -cbuffer matrices : register(b0) { Matrices matrices; }; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] int TextureIndex : TEXTUREINDEX0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - output.TextureIndex = input.TextureIndex; - output.Pos = mul(matrices.projection, mul(matrices.view, mul(matrices.model, float4(input.Pos.xyz, 1.0)))); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/descriptorindexing/descriptorindexing.vert.spv b/shaders/hlsl/descriptorindexing/descriptorindexing.vert.spv deleted file mode 100644 index cab40d81..00000000 Binary files a/shaders/hlsl/descriptorindexing/descriptorindexing.vert.spv and /dev/null differ diff --git a/shaders/hlsl/descriptorsets/cube.frag b/shaders/hlsl/descriptorsets/cube.frag deleted file mode 100644 index 854726c3..00000000 --- a/shaders/hlsl/descriptorsets/cube.frag +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - return textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/descriptorsets/cube.frag.spv b/shaders/hlsl/descriptorsets/cube.frag.spv deleted file mode 100644 index 58670396..00000000 Binary files a/shaders/hlsl/descriptorsets/cube.frag.spv and /dev/null differ diff --git a/shaders/hlsl/descriptorsets/cube.vert b/shaders/hlsl/descriptorsets/cube.vert deleted file mode 100644 index 68f4df3e..00000000 --- a/shaders/hlsl/descriptorsets/cube.vert +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBOMatrices { - float4x4 projection; - float4x4 view; - float4x4 model; -}; - -cbuffer uboMatrices : register(b0) { UBOMatrices uboMatrices; }; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(uboMatrices.projection, mul(uboMatrices.view, mul(uboMatrices.model, float4(input.Pos.xyz, 1.0)))); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/descriptorsets/cube.vert.spv b/shaders/hlsl/descriptorsets/cube.vert.spv deleted file mode 100644 index d2df4de2..00000000 Binary files a/shaders/hlsl/descriptorsets/cube.vert.spv and /dev/null differ diff --git a/shaders/hlsl/displacement/base.frag b/shaders/hlsl/displacement/base.frag deleted file mode 100644 index 78bda883..00000000 --- a/shaders/hlsl/displacement/base.frag +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2023 Sascha Willems - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); - -struct DSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 EyePos : POSITION0; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(DSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(float3(1.0, 1.0, 1.0)); - - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - - float4 IAmbient = float4(0.0, 0.0, 0.0, 1.0); - float4 IDiffuse = float4(1.0, 1.0, 1.0, 1.0) * max(dot(input.Normal, input.LightVec), 0.0); - - return float4((IAmbient + IDiffuse) * float4(textureColorMap.Sample(samplerColorMap, input.UV).rgb, 1.0)); -} \ No newline at end of file diff --git a/shaders/hlsl/displacement/base.frag.spv b/shaders/hlsl/displacement/base.frag.spv deleted file mode 100644 index 7c63170b..00000000 Binary files a/shaders/hlsl/displacement/base.frag.spv and /dev/null differ diff --git a/shaders/hlsl/displacement/base.vert b/shaders/hlsl/displacement/base.vert deleted file mode 100644 index da02b1cf..00000000 --- a/shaders/hlsl/displacement/base.vert +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct VSOutput -{ -[[vk::location(2)]] float4 Pos : POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = float4(input.Pos.xyz, 1.0); - output.UV = input.UV; - output.Normal = input.Normal; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/displacement/base.vert.spv b/shaders/hlsl/displacement/base.vert.spv deleted file mode 100644 index 5497168e..00000000 Binary files a/shaders/hlsl/displacement/base.vert.spv and /dev/null differ diff --git a/shaders/hlsl/displacement/displacement.tesc b/shaders/hlsl/displacement/displacement.tesc deleted file mode 100644 index ab2ac6bb..00000000 --- a/shaders/hlsl/displacement/displacement.tesc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2023 Sascha Willems - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; - float tessAlpha; - float tessStrength; - float tessLevel; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ -[[vk::location(2)]] float4 Pos : POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct HSOutput -{ -[[vk::location(2)]] float4 Pos : POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner : SV_InsideTessFactor; -}; - -ConstantsHSOutput ConstantsHS(InputPatch patch, uint InvocationID : SV_PrimitiveID) -{ - ConstantsHSOutput output = (ConstantsHSOutput)0; - output.TessLevelInner = ubo.tessLevel; - output.TessLevelOuter[0] = ubo.tessLevel; - output.TessLevelOuter[1] = ubo.tessLevel; - output.TessLevelOuter[2] = ubo.tessLevel; - return output; -} - -[domain("tri")] -[partitioning("integer")] -[outputtopology("triangle_cw")] -[outputcontrolpoints(3)] -[patchconstantfunc("ConstantsHS")] -[maxtessfactor(20.0f)] -HSOutput main(InputPatch patch, uint InvocationID : SV_OutputControlPointID) -{ - HSOutput output = (HSOutput)0; - output.Pos = patch[InvocationID].Pos; - output.Normal = patch[InvocationID].Normal; - output.UV = patch[InvocationID].UV; - return output; -} diff --git a/shaders/hlsl/displacement/displacement.tesc.spv b/shaders/hlsl/displacement/displacement.tesc.spv deleted file mode 100644 index 17a9bdfc..00000000 Binary files a/shaders/hlsl/displacement/displacement.tesc.spv and /dev/null differ diff --git a/shaders/hlsl/displacement/displacement.tese b/shaders/hlsl/displacement/displacement.tese deleted file mode 100644 index 86aeb19e..00000000 --- a/shaders/hlsl/displacement/displacement.tese +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2023 Sascha Willems - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; - float tessAlpha; - float tessStrength; - float tessLevel; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -Texture2D textureDisplacementMap : register(t1); -SamplerState samplerDisplacementMap : register(s1); - -struct HSOutput -{ -[[vk::location(2)]] float4 Pos : POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner : SV_InsideTessFactor; -}; - -struct DSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 EyesPos : POSITION0; -[[vk::location(3)]] float3 LightVec : TEXCOORD1; -}; - -[domain("tri")] -DSOutput main(ConstantsHSOutput input, float3 TessCoord : SV_DomainLocation, const OutputPatch patch) -{ - DSOutput output = (DSOutput)0; - output.Pos = (TessCoord.x * patch[0].Pos) + (TessCoord.y * patch[1].Pos) + (TessCoord.z * patch[2].Pos); - output.UV = mul(TessCoord.x, patch[0].UV) + mul(TessCoord.y, patch[1].UV) + mul(TessCoord.z, patch[2].UV); - output.Normal = TessCoord.x * patch[0].Normal + TessCoord.y * patch[1].Normal + TessCoord.z * patch[2].Normal; - - output.Pos.xyz += normalize(output.Normal) * (max(textureDisplacementMap.SampleLevel(samplerDisplacementMap, output.UV.xy, 0).a, 0.0) * ubo.tessStrength); - - output.EyesPos = output.Pos.xyz; - output.LightVec = normalize(ubo.lightPos.xyz - output.EyesPos); - - output.Pos = mul(ubo.projection, mul(ubo.model, output.Pos)); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/displacement/displacement.tese.spv b/shaders/hlsl/displacement/displacement.tese.spv deleted file mode 100644 index d028af64..00000000 Binary files a/shaders/hlsl/displacement/displacement.tese.spv and /dev/null differ diff --git a/shaders/hlsl/distancefieldfonts/bitmap.frag b/shaders/hlsl/distancefieldfonts/bitmap.frag deleted file mode 100644 index 456bfe86..00000000 --- a/shaders/hlsl/distancefieldfonts/bitmap.frag +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - return textureColor.Sample(samplerColor, inUV).aaaa; -} \ No newline at end of file diff --git a/shaders/hlsl/distancefieldfonts/bitmap.frag.spv b/shaders/hlsl/distancefieldfonts/bitmap.frag.spv deleted file mode 100644 index 6b721082..00000000 Binary files a/shaders/hlsl/distancefieldfonts/bitmap.frag.spv and /dev/null differ diff --git a/shaders/hlsl/distancefieldfonts/bitmap.vert b/shaders/hlsl/distancefieldfonts/bitmap.vert deleted file mode 100644 index 379daee9..00000000 --- a/shaders/hlsl/distancefieldfonts/bitmap.vert +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} diff --git a/shaders/hlsl/distancefieldfonts/bitmap.vert.spv b/shaders/hlsl/distancefieldfonts/bitmap.vert.spv deleted file mode 100644 index 5b4eecdc..00000000 Binary files a/shaders/hlsl/distancefieldfonts/bitmap.vert.spv and /dev/null differ diff --git a/shaders/hlsl/distancefieldfonts/sdf.frag b/shaders/hlsl/distancefieldfonts/sdf.frag deleted file mode 100644 index b645912c..00000000 --- a/shaders/hlsl/distancefieldfonts/sdf.frag +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2023 Sascha Willems - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 outlineColor; - float outlineWidth; - float outline; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - float dist = textureColor.Sample(samplerColor, inUV).a; - float smoothWidth = fwidth(dist); - float alpha = smoothstep(0.5 - smoothWidth, 0.5 + smoothWidth, dist); - float3 rgb = alpha.xxx; - - if (ubo.outline > 0.0) - { - float w = 1.0 - ubo.outlineWidth; - alpha = smoothstep(w - smoothWidth, w + smoothWidth, dist); - rgb += lerp(alpha.xxx, ubo.outlineColor.rgb, alpha); - } - - return float4(rgb, alpha); -} \ No newline at end of file diff --git a/shaders/hlsl/distancefieldfonts/sdf.frag.spv b/shaders/hlsl/distancefieldfonts/sdf.frag.spv deleted file mode 100644 index 562614d5..00000000 Binary files a/shaders/hlsl/distancefieldfonts/sdf.frag.spv and /dev/null differ diff --git a/shaders/hlsl/distancefieldfonts/sdf.vert b/shaders/hlsl/distancefieldfonts/sdf.vert deleted file mode 100644 index a16d01d3..00000000 --- a/shaders/hlsl/distancefieldfonts/sdf.vert +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2023 Sascha Willems - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 outlineColor; - float outlineWidth; - float outline; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} diff --git a/shaders/hlsl/distancefieldfonts/sdf.vert.spv b/shaders/hlsl/distancefieldfonts/sdf.vert.spv deleted file mode 100644 index 44a1115d..00000000 Binary files a/shaders/hlsl/distancefieldfonts/sdf.vert.spv and /dev/null differ diff --git a/shaders/hlsl/dynamicuniformbuffer/base.frag b/shaders/hlsl/dynamicuniformbuffer/base.frag deleted file mode 100644 index b800903c..00000000 --- a/shaders/hlsl/dynamicuniformbuffer/base.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main([[vk::location(0)]] float3 Color : COLOR0) : SV_TARGET -{ - return float4(Color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/dynamicuniformbuffer/base.frag.spv b/shaders/hlsl/dynamicuniformbuffer/base.frag.spv deleted file mode 100644 index 870fb6c1..00000000 Binary files a/shaders/hlsl/dynamicuniformbuffer/base.frag.spv and /dev/null differ diff --git a/shaders/hlsl/dynamicuniformbuffer/base.vert b/shaders/hlsl/dynamicuniformbuffer/base.vert deleted file mode 100644 index 7cb43933..00000000 --- a/shaders/hlsl/dynamicuniformbuffer/base.vert +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Color : COLOR0; -}; - -struct UboView -{ - float4x4 projection; - float4x4 view; -}; -cbuffer uboView : register(b0) { UboView uboView; }; - -struct UboInstance -{ - float4x4 model; -}; -cbuffer uboInstance : register(b1) { UboInstance uboInstance; }; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - float4x4 modelView = mul(uboView.view, uboInstance.model); - float3 worldPos = mul(modelView, float4(input.Pos, 1.0)).xyz; - output.Pos = mul(uboView.projection, mul(modelView, float4(input.Pos.xyz, 1.0))); - return output; -} diff --git a/shaders/hlsl/dynamicuniformbuffer/base.vert.spv b/shaders/hlsl/dynamicuniformbuffer/base.vert.spv deleted file mode 100644 index 8c66fc5e..00000000 Binary files a/shaders/hlsl/dynamicuniformbuffer/base.vert.spv and /dev/null differ diff --git a/shaders/hlsl/gears/gears.frag b/shaders/hlsl/gears/gears.frag deleted file mode 100644 index 276b830a..00000000 --- a/shaders/hlsl/gears/gears.frag +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 EyePos : POSITION0; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - - float4 IAmbient = float4(0.2, 0.2, 0.2, 1.0); - float4 IDiffuse = float4(0.5, 0.5, 0.5, 0.5) * max(dot(input.Normal, input.LightVec), 0.0); - float specular = 0.25; - float4 ISpecular = float4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 0.8) * specular; - - return float4((IAmbient + IDiffuse) * float4(input.Color, 1.0) + ISpecular); -} \ No newline at end of file diff --git a/shaders/hlsl/gears/gears.frag.spv b/shaders/hlsl/gears/gears.frag.spv deleted file mode 100644 index 59596abb..00000000 Binary files a/shaders/hlsl/gears/gears.frag.spv and /dev/null differ diff --git a/shaders/hlsl/gears/gears.vert b/shaders/hlsl/gears/gears.vert deleted file mode 100644 index 67590b99..00000000 --- a/shaders/hlsl/gears/gears.vert +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2023 Sascha Willems - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4 lightpos; - float4x4 model[3]; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 EyePos : POSITION0; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input, uint InstanceIndex : SV_InstanceID) -{ - VSOutput output = (VSOutput)0; - output.Normal = normalize(mul((float3x3)transpose(ubo.model[InstanceIndex]), input.Normal).xyz); - output.Color = input.Color; - float4x4 modelView = mul(ubo.view, ubo.model[InstanceIndex]); - float4 pos = mul(modelView, input.Pos); - output.EyePos = mul(modelView, pos).xyz; - float4 lightPos = mul(float4(ubo.lightpos.xyz, 1.0), modelView); - output.LightVec = normalize(lightPos.xyz - output.EyePos); - output.Pos = mul(ubo.projection, pos); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/gears/gears.vert.spv b/shaders/hlsl/gears/gears.vert.spv deleted file mode 100644 index 254ebfd9..00000000 Binary files a/shaders/hlsl/gears/gears.vert.spv and /dev/null differ diff --git a/shaders/hlsl/geometryshader/base.frag b/shaders/hlsl/geometryshader/base.frag deleted file mode 100644 index b800903c..00000000 --- a/shaders/hlsl/geometryshader/base.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main([[vk::location(0)]] float3 Color : COLOR0) : SV_TARGET -{ - return float4(Color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/geometryshader/base.frag.spv b/shaders/hlsl/geometryshader/base.frag.spv deleted file mode 100644 index 870fb6c1..00000000 Binary files a/shaders/hlsl/geometryshader/base.frag.spv and /dev/null differ diff --git a/shaders/hlsl/geometryshader/base.vert b/shaders/hlsl/geometryshader/base.vert deleted file mode 100644 index 8179b490..00000000 --- a/shaders/hlsl/geometryshader/base.vert +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -struct VSOutput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Pos = float4(input.Pos.xyz, 1.0); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/geometryshader/base.vert.spv b/shaders/hlsl/geometryshader/base.vert.spv deleted file mode 100644 index 1c7f9769..00000000 Binary files a/shaders/hlsl/geometryshader/base.vert.spv and /dev/null differ diff --git a/shaders/hlsl/geometryshader/mesh.frag b/shaders/hlsl/geometryshader/mesh.frag deleted file mode 100644 index 189e9955..00000000 --- a/shaders/hlsl/geometryshader/mesh.frag +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -struct GSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(GSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.1, 0.1, 0.1); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/geometryshader/mesh.frag.spv b/shaders/hlsl/geometryshader/mesh.frag.spv deleted file mode 100644 index a2843e1c..00000000 Binary files a/shaders/hlsl/geometryshader/mesh.frag.spv and /dev/null differ diff --git a/shaders/hlsl/geometryshader/mesh.vert b/shaders/hlsl/geometryshader/mesh.vert deleted file mode 100644 index cfa1dcf9..00000000 --- a/shaders/hlsl/geometryshader/mesh.vert +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, input.Pos)); - - float4 pos = mul(ubo.model, float4(input.Pos.xyz, 1.0)); - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - - float3 lightPos = float3(1.0f, -1.0f, 1.0f); - output.LightVec = lightPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} diff --git a/shaders/hlsl/geometryshader/mesh.vert.spv b/shaders/hlsl/geometryshader/mesh.vert.spv deleted file mode 100644 index 2a233ad2..00000000 Binary files a/shaders/hlsl/geometryshader/mesh.vert.spv and /dev/null differ diff --git a/shaders/hlsl/geometryshader/normaldebug.geom b/shaders/hlsl/geometryshader/normaldebug.geom deleted file mode 100644 index 0c5a0379..00000000 --- a/shaders/hlsl/geometryshader/normaldebug.geom +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Google LLC - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -struct GSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -}; - -[maxvertexcount(6)] -void main(triangle VSOutput input[3], inout LineStream outStream) -{ - float normalLength = 0.02; - for(int i=0; i<3; i++) - { - float3 pos = input[i].Pos.xyz; - float3 normal = input[i].Normal.xyz; - - GSOutput output = (GSOutput)0; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(pos, 1.0))); - output.Color = float3(1.0, 0.0, 0.0); - outStream.Append( output ); - - output.Pos = mul(ubo.projection, mul(ubo.model, float4(pos + normal * normalLength, 1.0))); - output.Color = float3(0.0, 0.0, 1.0); - outStream.Append( output ); - - outStream.RestartStrip(); - } -} \ No newline at end of file diff --git a/shaders/hlsl/geometryshader/normaldebug.geom.spv b/shaders/hlsl/geometryshader/normaldebug.geom.spv deleted file mode 100644 index 31886c77..00000000 Binary files a/shaders/hlsl/geometryshader/normaldebug.geom.spv and /dev/null differ diff --git a/shaders/hlsl/gltfloading/mesh.frag b/shaders/hlsl/gltfloading/mesh.frag deleted file mode 100644 index a574c7a1..00000000 --- a/shaders/hlsl/gltfloading/mesh.frag +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t0, space1); -SamplerState samplerColorMap : register(s0, space1); - -struct PushConsts { - float4x4 model; -}; -[[vk::push_constant]] PushConsts primitive; - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/gltfloading/mesh.frag.spv b/shaders/hlsl/gltfloading/mesh.frag.spv deleted file mode 100644 index 4eafff86..00000000 Binary files a/shaders/hlsl/gltfloading/mesh.frag.spv and /dev/null differ diff --git a/shaders/hlsl/gltfloading/mesh.vert b/shaders/hlsl/gltfloading/mesh.vert deleted file mode 100644 index 3f46fbc5..00000000 --- a/shaders/hlsl/gltfloading/mesh.vert +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4 lightPos; - float4 viewPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct PushConsts { - float4x4 model; -}; -[[vk::push_constant]] PushConsts primitive; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(primitive.model, float4(input.Pos.xyz, 1.0)))); - - float4 pos = mul(ubo.view, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.view, input.Normal); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/gltfloading/mesh.vert.spv b/shaders/hlsl/gltfloading/mesh.vert.spv deleted file mode 100644 index 612219e6..00000000 Binary files a/shaders/hlsl/gltfloading/mesh.vert.spv and /dev/null differ diff --git a/shaders/hlsl/gltfscenerendering/scene.frag b/shaders/hlsl/gltfscenerendering/scene.frag deleted file mode 100644 index 62aad5d9..00000000 --- a/shaders/hlsl/gltfscenerendering/scene.frag +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t0, space1); -SamplerState samplerColorMap : register(s0, space1); -Texture2D textureNormalMap : register(t1, space1); -SamplerState samplerNormalMap : register(s1, space1); - -[[vk::constant_id(0)]] const bool ALPHA_MASK = false; -[[vk::constant_id(1)]] const float ALPHA_MASK_CUTOFF = 0.0; - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -[[vk::location(5)]] float4 Tangent : TEXCOORD3; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0); - - if (ALPHA_MASK) { - if (color.a < ALPHA_MASK_CUTOFF) { - discard; - } - } - - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent.xyz); - float3 B = cross(input.Normal, input.Tangent.xyz) * input.Tangent.w; - float3x3 TBN = float3x3(T, B, N); - N = mul(normalize(textureNormalMap.Sample(samplerNormalMap, input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - - const float ambient = 0.1; - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), ambient).rrr; - float3 specular = pow(max(dot(R, V), 0.0), 32.0); - return float4(diffuse * color.rgb + specular, color.a); -} \ No newline at end of file diff --git a/shaders/hlsl/gltfscenerendering/scene.frag.spv b/shaders/hlsl/gltfscenerendering/scene.frag.spv deleted file mode 100644 index 4774d074..00000000 Binary files a/shaders/hlsl/gltfscenerendering/scene.frag.spv and /dev/null differ diff --git a/shaders/hlsl/gltfscenerendering/scene.vert b/shaders/hlsl/gltfscenerendering/scene.vert deleted file mode 100644 index 41edd8be..00000000 --- a/shaders/hlsl/gltfscenerendering/scene.vert +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -[[vk::location(4)]] float4 Tangent : TEXCOORD1; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4 lightPos; - float4 viewPos; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -struct PushConsts { - float4x4 model; -}; -[[vk::push_constant]] PushConsts primitive; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -[[vk::location(5)]] float4 Tangent : TEXCOORD3; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Tangent = input.Tangent; - - float4x4 modelView = mul(ubo.view, primitive.model); - - output.Pos = mul(ubo.projection, mul(modelView, float4(input.Pos.xyz, 1.0))); - - output.Normal = mul((float3x3)primitive.model, input.Normal); - float4 pos = mul(primitive.model, float4(input.Pos, 1.0)); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/gltfscenerendering/scene.vert.spv b/shaders/hlsl/gltfscenerendering/scene.vert.spv deleted file mode 100644 index 35000d17..00000000 Binary files a/shaders/hlsl/gltfscenerendering/scene.vert.spv and /dev/null differ diff --git a/shaders/hlsl/hdr/bloom.frag b/shaders/hlsl/hdr/bloom.frag deleted file mode 100644 index 13c5e14a..00000000 --- a/shaders/hlsl/hdr/bloom.frag +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor0 : register(t0); -SamplerState samplerColor0 : register(s0); -Texture2D textureColor1 : register(t1); -SamplerState samplerColor1 : register(s1); - -[[vk::constant_id(0)]] const int dir = 0; - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - // From the OpenGL Super bible - const float weights[] = { 0.0024499299678342, - 0.0043538453346397, - 0.0073599963704157, - 0.0118349786570722, - 0.0181026699707781, - 0.0263392293891488, - 0.0364543006660986, - 0.0479932050577658, - 0.0601029809166942, - 0.0715974486241365, - 0.0811305381519717, - 0.0874493212267511, - 0.0896631113333857, - 0.0874493212267511, - 0.0811305381519717, - 0.0715974486241365, - 0.0601029809166942, - 0.0479932050577658, - 0.0364543006660986, - 0.0263392293891488, - 0.0181026699707781, - 0.0118349786570722, - 0.0073599963704157, - 0.0043538453346397, - 0.0024499299678342}; - - - const float blurScale = 0.003; - const float blurStrength = 1.0; - - float ar = 1.0; - // Aspect ratio for vertical blur pass - if (dir == 1) - { - float2 ts; - textureColor1.GetDimensions(ts.x, ts.y); - ar = ts.y / ts.x; - } - - float2 P = inUV.yx - float2(0, (25 >> 1) * ar * blurScale); - - float4 color = float4(0.0, 0.0, 0.0, 0.0); - for (int i = 0; i < 25; i++) - { - float2 dv = float2(0.0, i * blurScale) * ar; - color += textureColor1.Sample(samplerColor1, P + dv) * weights[i] * blurStrength; - } - - return color; -} \ No newline at end of file diff --git a/shaders/hlsl/hdr/bloom.frag.spv b/shaders/hlsl/hdr/bloom.frag.spv deleted file mode 100644 index a9f90348..00000000 Binary files a/shaders/hlsl/hdr/bloom.frag.spv and /dev/null differ diff --git a/shaders/hlsl/hdr/bloom.vert b/shaders/hlsl/hdr/bloom.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/hdr/bloom.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/hdr/bloom.vert.spv b/shaders/hlsl/hdr/bloom.vert.spv deleted file mode 100644 index 46c4b31f..00000000 Binary files a/shaders/hlsl/hdr/bloom.vert.spv and /dev/null differ diff --git a/shaders/hlsl/hdr/composition.frag b/shaders/hlsl/hdr/composition.frag deleted file mode 100644 index 41c9be65..00000000 --- a/shaders/hlsl/hdr/composition.frag +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor0 : register(t0); -SamplerState samplerColor0 : register(s0); -Texture2D textureColor1 : register(t1); -SamplerState samplerColor1 : register(s1); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - return textureColor0.Sample(samplerColor0, inUV); -} \ No newline at end of file diff --git a/shaders/hlsl/hdr/composition.frag.spv b/shaders/hlsl/hdr/composition.frag.spv deleted file mode 100644 index 9b0e3a0a..00000000 Binary files a/shaders/hlsl/hdr/composition.frag.spv and /dev/null differ diff --git a/shaders/hlsl/hdr/composition.vert b/shaders/hlsl/hdr/composition.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/hdr/composition.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/hdr/composition.vert.spv b/shaders/hlsl/hdr/composition.vert.spv deleted file mode 100644 index 46c4b31f..00000000 Binary files a/shaders/hlsl/hdr/composition.vert.spv and /dev/null differ diff --git a/shaders/hlsl/hdr/gbuffer.frag b/shaders/hlsl/hdr/gbuffer.frag deleted file mode 100644 index c1fdafc2..00000000 --- a/shaders/hlsl/hdr/gbuffer.frag +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureEnvMap : register(t1); -SamplerState samplerEnvMap : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 UVW : TEXCOORD0; -[[vk::location(1)]] float3 Pos : POSITION0; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -struct FSOutput -{ - float4 Color0 : SV_TARGET0; - float4 Color1 : SV_TARGET1; -}; - -[[vk::constant_id(0)]] const int type = 0; - -#define PI 3.1415926 -#define TwoPI (2.0 * PI) - -struct UBO { - float4x4 projection; - float4x4 modelview; - float4x4 inverseModelview; - float exposure; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -FSOutput main(VSOutput input) -{ - FSOutput output = (FSOutput)0; - float4 color; - float3 wcNormal; - - switch (type) { - case 0: // Skybox - { - float3 normal = normalize(input.UVW); - color = textureEnvMap.Sample(samplerEnvMap, normal); - } - break; - - case 1: // Reflect - { - float3 wViewVec = mul((float4x3)ubo.inverseModelview, normalize(input.ViewVec)).xyz; - float3 normal = normalize(input.Normal); - float3 wNormal = mul((float4x3)ubo.inverseModelview, normal).xyz; - - float NdotL = max(dot(normal, input.LightVec), 0.0); - - float3 eyeDir = normalize(input.ViewVec); - float3 halfVec = normalize(input.LightVec + eyeDir); - float NdotH = max(dot(normal, halfVec), 0.0); - float NdotV = max(dot(normal, eyeDir), 0.0); - float VdotH = max(dot(eyeDir, halfVec), 0.0); - - // Geometric attenuation - float NH2 = 2.0 * NdotH; - float g1 = (NH2 * NdotV) / VdotH; - float g2 = (NH2 * NdotL) / VdotH; - float geoAtt = min(1.0, min(g1, g2)); - - const float F0 = 0.6; - const float k = 0.2; - - // Fresnel (schlick approximation) - float fresnel = pow(1.0 - VdotH, 5.0); - fresnel *= (1.0 - F0); - fresnel += F0; - - float spec = (fresnel * geoAtt) / (NdotV * NdotL * 3.14); - - color = textureEnvMap.Sample(samplerEnvMap, reflect(-wViewVec, wNormal)); - - color = float4(color.rgb * NdotL * (k + spec * (1.0 - k)), 1.0); - } - break; - - case 2: // Refract - { - float3 wViewVec = mul((float4x3)ubo.inverseModelview, normalize(input.ViewVec)).xyz; - float3 wNormal = mul((float4x3)ubo.inverseModelview, input.Normal).xyz; - color = textureEnvMap.Sample(samplerEnvMap, refract(-wViewVec, wNormal, 1.0/1.6)); - } - break; - } - - - // Color with manual exposure into attachment 0 - output.Color0.rgb = float3(1.0, 1.0, 1.0) - exp(-color.rgb * ubo.exposure); - - // Bright parts for bloom into attachment 1 - float l = dot(output.Color0.rgb, float3(0.2126, 0.7152, 0.0722)); - float threshold = 0.75; - output.Color1.rgb = (l > threshold) ? output.Color0.rgb : float3(0.0, 0.0, 0.0); - output.Color1.a = 1.0; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/hdr/gbuffer.frag.spv b/shaders/hlsl/hdr/gbuffer.frag.spv deleted file mode 100644 index 022e1da1..00000000 Binary files a/shaders/hlsl/hdr/gbuffer.frag.spv and /dev/null differ diff --git a/shaders/hlsl/hdr/gbuffer.vert b/shaders/hlsl/hdr/gbuffer.vert deleted file mode 100644 index c833a812..00000000 --- a/shaders/hlsl/hdr/gbuffer.vert +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -[[vk::constant_id(0)]] const int type = 0; - -struct UBO { - float4x4 projection; - float4x4 modelview; - float4x4 inverseModelview; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UVW : TEXCOORD0; -[[vk::location(1)]] float3 WorldPos : POSITION0; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UVW = input.Pos; - - switch(type) { - case 0: // Skybox - output.WorldPos = mul((float4x3)ubo.modelview, input.Pos).xyz; - output.Pos = mul(ubo.projection, float4(output.WorldPos, 1.0)); - break; - case 1: // Object - output.WorldPos = mul(ubo.modelview, float4(input.Pos, 1.0)).xyz; - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(input.Pos.xyz, 1.0))); - break; - } - output.WorldPos = mul(ubo.modelview, float4(input.Pos, 1.0)).xyz; - output.Normal = mul((float4x3)ubo.modelview, input.Normal).xyz; - - float3 lightPos = float3(0.0f, -5.0f, 5.0f); - output.LightVec = lightPos.xyz - output.WorldPos.xyz; - output.ViewVec = -output.WorldPos.xyz; - return output; -} diff --git a/shaders/hlsl/hdr/gbuffer.vert.spv b/shaders/hlsl/hdr/gbuffer.vert.spv deleted file mode 100644 index c55b04bc..00000000 Binary files a/shaders/hlsl/hdr/gbuffer.vert.spv and /dev/null differ diff --git a/shaders/hlsl/imgui/scene.frag b/shaders/hlsl/imgui/scene.frag deleted file mode 100644 index cdb2d089..00000000 --- a/shaders/hlsl/imgui/scene.frag +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float diffuse = max(dot(N, L), 0.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse * input.Color + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/imgui/scene.frag.spv b/shaders/hlsl/imgui/scene.frag.spv deleted file mode 100644 index 5893f073..00000000 Binary files a/shaders/hlsl/imgui/scene.frag.spv and /dev/null differ diff --git a/shaders/hlsl/imgui/scene.vert b/shaders/hlsl/imgui/scene.vert deleted file mode 100644 index f7a59099..00000000 --- a/shaders/hlsl/imgui/scene.vert +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - float3 lPos = mul((float4x3)ubo.model, ubo.lightPos.xyz).xyz; - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/imgui/scene.vert.spv b/shaders/hlsl/imgui/scene.vert.spv deleted file mode 100644 index c2d90846..00000000 Binary files a/shaders/hlsl/imgui/scene.vert.spv and /dev/null differ diff --git a/shaders/hlsl/imgui/ui.frag b/shaders/hlsl/imgui/ui.frag deleted file mode 100644 index 562acfe4..00000000 --- a/shaders/hlsl/imgui/ui.frag +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D fontTexture : register(t0); -SamplerState fontSampler : register(s0); - -struct VSOutput -{ -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float4 Color : COLOR0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - return input.Color * fontTexture.Sample(fontSampler, input.UV); -} \ No newline at end of file diff --git a/shaders/hlsl/imgui/ui.frag.spv b/shaders/hlsl/imgui/ui.frag.spv deleted file mode 100644 index 282a17fd..00000000 Binary files a/shaders/hlsl/imgui/ui.frag.spv and /dev/null differ diff --git a/shaders/hlsl/imgui/ui.vert b/shaders/hlsl/imgui/ui.vert deleted file mode 100644 index df4e48eb..00000000 --- a/shaders/hlsl/imgui/ui.vert +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float2 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float4 Color : COLOR0; -}; - -struct PushConstants -{ - float2 scale; - float2 translate; -}; - -[[vk::push_constant]] -PushConstants pushConstants; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float4 Color : COLOR0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - output.Color = input.Color; - output.Pos = float4(input.Pos * pushConstants.scale + pushConstants.translate, 0.0, 1.0); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/imgui/ui.vert.spv b/shaders/hlsl/imgui/ui.vert.spv deleted file mode 100644 index 86369ec3..00000000 Binary files a/shaders/hlsl/imgui/ui.vert.spv and /dev/null differ diff --git a/shaders/hlsl/indirectdraw/ground.frag b/shaders/hlsl/indirectdraw/ground.frag deleted file mode 100644 index 9b1a1a64..00000000 --- a/shaders/hlsl/indirectdraw/ground.frag +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t2); -SamplerState samplerColor : register(s2); - -struct VSOutput -{ -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureColor.Sample(samplerColor, input.UV); - return float4(color.rgb, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/indirectdraw/ground.frag.spv b/shaders/hlsl/indirectdraw/ground.frag.spv deleted file mode 100644 index 4f6047ff..00000000 Binary files a/shaders/hlsl/indirectdraw/ground.frag.spv and /dev/null differ diff --git a/shaders/hlsl/indirectdraw/ground.vert b/shaders/hlsl/indirectdraw/ground.vert deleted file mode 100644 index c6caf9e7..00000000 --- a/shaders/hlsl/indirectdraw/ground.vert +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV * 32.0; - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(input.Pos.xyz, 1.0))); - return output; -} diff --git a/shaders/hlsl/indirectdraw/ground.vert.spv b/shaders/hlsl/indirectdraw/ground.vert.spv deleted file mode 100644 index 38e2a114..00000000 Binary files a/shaders/hlsl/indirectdraw/ground.vert.spv and /dev/null differ diff --git a/shaders/hlsl/indirectdraw/indirectdraw.frag b/shaders/hlsl/indirectdraw/indirectdraw.frag deleted file mode 100644 index 395a5a2b..00000000 --- a/shaders/hlsl/indirectdraw/indirectdraw.frag +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2DArray textureArray : register(t1); -SamplerState samplerArray : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureArray.Sample(samplerArray, input.UV); - - if (color.a < 0.5) - { - clip(-1); - } - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 ambient = float3(0.65, 0.65, 0.65); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - return float4((ambient + diffuse) * color.rgb, 1.0); -} diff --git a/shaders/hlsl/indirectdraw/indirectdraw.frag.spv b/shaders/hlsl/indirectdraw/indirectdraw.frag.spv deleted file mode 100644 index a738a2ab..00000000 Binary files a/shaders/hlsl/indirectdraw/indirectdraw.frag.spv and /dev/null differ diff --git a/shaders/hlsl/indirectdraw/indirectdraw.vert b/shaders/hlsl/indirectdraw/indirectdraw.vert deleted file mode 100644 index 3d2b8afe..00000000 --- a/shaders/hlsl/indirectdraw/indirectdraw.vert +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -[[vk::location(4)]] float3 instancePos : POSITION1; -[[vk::location(5)]] float3 instanceRot : TEXCOORD1; -[[vk::location(6)]] float instanceScale : TEXCOORD2; -[[vk::location(7)]] int instanceTexIndex : TEXCOORD3; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.UV = float3(input.UV, input.instanceTexIndex); - - float4x4 mx, my, mz; - - // rotate around x - float s = sin(input.instanceRot.x); - float c = cos(input.instanceRot.x); - - mx[0] = float4(c, s, 0.0, 0.0); - mx[1] = float4(-s, c, 0.0, 0.0); - mx[2] = float4(0.0, 0.0, 1.0, 0.0); - mx[3] = float4(0.0, 0.0, 0.0, 1.0); - - // rotate around y - s = sin(input.instanceRot.y); - c = cos(input.instanceRot.y); - - my[0] = float4(c, 0.0, s, 0.0); - my[1] = float4(0.0, 1.0, 0.0, 0.0); - my[2] = float4(-s, 0.0, c, 0.0); - my[3] = float4(0.0, 0.0, 0.0, 1.0); - - // rot around z - s = sin(input.instanceRot.z); - c = cos(input.instanceRot.z); - - mz[0] = float4(1.0, 0.0, 0.0, 0.0); - mz[1] = float4(0.0, c, s, 0.0); - mz[2] = float4(0.0, -s, c, 0.0); - mz[3] = float4(0.0, 0.0, 0.0, 1.0); - - float4x4 rotMat = mul(mz, mul(my, mx)); - - output.Normal = mul((float4x3)rotMat, input.Normal).xyz; - - float4 pos = mul(rotMat, float4((input.Pos.xyz * input.instanceScale) + input.instancePos, 1.0)); - - output.Pos = mul(ubo.projection, mul(ubo.modelview, pos)); - - float4 wPos = mul(ubo.modelview, float4(pos.xyz, 1.0)); - float4 lPos = float4(0.0, -5.0, 0.0, 1.0); - output.LightVec = lPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} diff --git a/shaders/hlsl/indirectdraw/indirectdraw.vert.spv b/shaders/hlsl/indirectdraw/indirectdraw.vert.spv deleted file mode 100644 index 1c53a5de..00000000 Binary files a/shaders/hlsl/indirectdraw/indirectdraw.vert.spv and /dev/null differ diff --git a/shaders/hlsl/indirectdraw/skysphere.frag b/shaders/hlsl/indirectdraw/skysphere.frag deleted file mode 100644 index 36aef596..00000000 --- a/shaders/hlsl/indirectdraw/skysphere.frag +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t2); -SamplerState samplerColor : register(s2); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - const float4 gradientStart = float4(0.93, 0.9, 0.81, 1.0); - const float4 gradientEnd = float4(0.35, 0.5, 1.0, 1.0); - return lerp(gradientStart, gradientEnd, min(0.5 - (inUV.y + 0.05), 0.5)/0.15 + 0.5); -} \ No newline at end of file diff --git a/shaders/hlsl/indirectdraw/skysphere.frag.spv b/shaders/hlsl/indirectdraw/skysphere.frag.spv deleted file mode 100644 index 343023a7..00000000 Binary files a/shaders/hlsl/indirectdraw/skysphere.frag.spv and /dev/null differ diff --git a/shaders/hlsl/indirectdraw/skysphere.vert b/shaders/hlsl/indirectdraw/skysphere.vert deleted file mode 100644 index c03aefdb..00000000 --- a/shaders/hlsl/indirectdraw/skysphere.vert +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - // Skysphere always at center, only use rotation part of modelview matrix - output.Pos = mul(ubo.projection, float4(mul((float3x3)ubo.modelview, input.Pos.xyz), 1)); - return output; -} diff --git a/shaders/hlsl/indirectdraw/skysphere.vert.spv b/shaders/hlsl/indirectdraw/skysphere.vert.spv deleted file mode 100644 index 8f580a6d..00000000 Binary files a/shaders/hlsl/indirectdraw/skysphere.vert.spv and /dev/null differ diff --git a/shaders/hlsl/inlineuniformblocks/pbr.frag b/shaders/hlsl/inlineuniformblocks/pbr.frag deleted file mode 100644 index ad1bf284..00000000 --- a/shaders/hlsl/inlineuniformblocks/pbr.frag +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 WorldPos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -// Inline uniform block -struct UniformInline { - float roughness; - float metallic; - float r; - float g; - float b; - float ambient; -}; -cbuffer material : register(b0, space1) { UniformInline material; }; - -#define PI 3.14159265359 - -float3 materialcolor() -{ - return float3(material.r, material.g, material.b); -} - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -float3 F_Schlick(float cosTheta, float metallic) -{ - float3 F0 = lerp(float3(0.04, 0.04, 0.04), materialcolor(), metallic); // * material.specular - float3 F = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); - return F; -} - -// Specular BRDF composition -------------------------------------------- - -float3 BRDF(float3 L, float3 V, float3 N, float metallic, float roughness) -{ - // Precalculate vectors and dot products - float3 H = normalize (V + L); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - float dotLH = clamp(dot(L, H), 0.0, 1.0); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - - // Light color fixed - float3 lightColor = float3(1.0, 1.0, 1.0); - - float3 color = float3(0.0, 0.0, 0.0); - - if (dotNL > 0.0) - { - float rroughness = max(0.05, roughness); - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, rroughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, rroughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - float3 F = F_Schlick(dotNV, metallic); - - float3 spec = D * F * G / (4.0 * dotNL * dotNV); - - color += spec * dotNL * lightColor; - } - - return color; -} - -// ---------------------------------------------------------------------------- -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 V = normalize(ubo.camPos - input.WorldPos); - - float roughness = material.roughness; - - // Specular contribution - float3 lightPos = float3(0.0f, 0.0f, 10.0f); - float3 Lo = float3(0.0, 0.0, 0.0); - float3 L = normalize(lightPos.xyz - input.WorldPos); - Lo += BRDF(L, V, N, material.metallic, roughness); - - // Combine with ambient - float3 color = materialcolor() * material.ambient; - color += Lo; - - // Gamma correct - color = pow(color, float3(0.4545, 0.4545, 0.4545)); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/inlineuniformblocks/pbr.frag.spv b/shaders/hlsl/inlineuniformblocks/pbr.frag.spv deleted file mode 100644 index 94ee1472..00000000 Binary files a/shaders/hlsl/inlineuniformblocks/pbr.frag.spv and /dev/null differ diff --git a/shaders/hlsl/inlineuniformblocks/pbr.vert b/shaders/hlsl/inlineuniformblocks/pbr.vert deleted file mode 100644 index b9f5c1b3..00000000 --- a/shaders/hlsl/inlineuniformblocks/pbr.vert +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 WorldPos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -struct PushConsts { - float3 objPos; -}; -[[vk::push_constant]] PushConsts pushConsts; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - float3 locPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.WorldPos = locPos + pushConsts.objPos; - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - output.Pos = mul(ubo.projection, mul(ubo.view, float4(output.WorldPos, 1.0))); - return output; -} diff --git a/shaders/hlsl/inlineuniformblocks/pbr.vert.spv b/shaders/hlsl/inlineuniformblocks/pbr.vert.spv deleted file mode 100644 index 2739d752..00000000 Binary files a/shaders/hlsl/inlineuniformblocks/pbr.vert.spv and /dev/null differ diff --git a/shaders/hlsl/inputattachments/attachmentread.frag b/shaders/hlsl/inputattachments/attachmentread.frag deleted file mode 100644 index 28ef33ed..00000000 --- a/shaders/hlsl/inputattachments/attachmentread.frag +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC - -[[vk::input_attachment_index(0)]][[vk::binding(0)]] SubpassInput inputColor; -[[vk::input_attachment_index(1)]][[vk::binding(1)]] SubpassInput inputDepth; - -struct UBO { - float2 brightnessContrast; - float2 range; - int attachmentIndex; -}; - -cbuffer ubo : register(b2) { UBO ubo; } - -float3 brightnessContrast(float3 color, float brightness, float contrast) { - return (color - 0.5) * contrast + 0.5 + brightness; -} - -float4 main() : SV_TARGET -{ - // Apply brightness and contrast filer to color input - if (ubo.attachmentIndex == 0) { - // Read color from previous color input attachment - float3 color = inputColor.SubpassLoad().rgb; - return float4(brightnessContrast(color, ubo.brightnessContrast[0], ubo.brightnessContrast[1]), 1); - } - - // Visualize depth input range - if (ubo.attachmentIndex == 1) { - // Read depth from previous depth input attachment - float depth = inputDepth.SubpassLoad().r; - return float4((depth - ubo.range[0]) * 1.0 / (ubo.range[1] - ubo.range[0]).xxx, 1); - } - - return 0.xxxx; -} \ No newline at end of file diff --git a/shaders/hlsl/inputattachments/attachmentread.frag.spv b/shaders/hlsl/inputattachments/attachmentread.frag.spv deleted file mode 100644 index 4450a405..00000000 Binary files a/shaders/hlsl/inputattachments/attachmentread.frag.spv and /dev/null differ diff --git a/shaders/hlsl/inputattachments/attachmentread.vert b/shaders/hlsl/inputattachments/attachmentread.vert deleted file mode 100644 index fa447fcf..00000000 --- a/shaders/hlsl/inputattachments/attachmentread.vert +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main(uint VertexIndex : SV_VertexID) : SV_POSITION -{ - return float4(float2((VertexIndex << 1) & 2, VertexIndex & 2) * 2.0f - 1.0f, 0.0f, 1.0f); -} \ No newline at end of file diff --git a/shaders/hlsl/inputattachments/attachmentread.vert.spv b/shaders/hlsl/inputattachments/attachmentread.vert.spv deleted file mode 100644 index ef562307..00000000 Binary files a/shaders/hlsl/inputattachments/attachmentread.vert.spv and /dev/null differ diff --git a/shaders/hlsl/inputattachments/attachmentwrite.frag b/shaders/hlsl/inputattachments/attachmentwrite.frag deleted file mode 100644 index 35ea3f3a..00000000 --- a/shaders/hlsl/inputattachments/attachmentwrite.frag +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Color : COLOR0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - // Toon shading color attachment output - float intensity = dot(normalize(input.Normal), normalize(input.LightVec)); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - return float4(input.Color * 3.0 * shade, 1); - - // Depth attachment does not need to be explicitly written -} \ No newline at end of file diff --git a/shaders/hlsl/inputattachments/attachmentwrite.frag.spv b/shaders/hlsl/inputattachments/attachmentwrite.frag.spv deleted file mode 100644 index 6db6c47d..00000000 Binary files a/shaders/hlsl/inputattachments/attachmentwrite.frag.spv and /dev/null differ diff --git a/shaders/hlsl/inputattachments/attachmentwrite.vert b/shaders/hlsl/inputattachments/attachmentwrite.vert deleted file mode 100644 index eff5642a..00000000 --- a/shaders/hlsl/inputattachments/attachmentwrite.vert +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 Normal : NORMAL0; -}; - -struct UBO { - float4x4 projection; - float4x4 model; - float4x4 view; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos, 1.0)))); - output.Color = input.Color; - output.Normal = input.Normal; - output.LightVec = float3(0.0f, 5.0f, 15.0f) - input.Pos; - output.ViewVec = -input.Pos.xyz; - return output; -} diff --git a/shaders/hlsl/inputattachments/attachmentwrite.vert.spv b/shaders/hlsl/inputattachments/attachmentwrite.vert.spv deleted file mode 100644 index c77bfa5b..00000000 Binary files a/shaders/hlsl/inputattachments/attachmentwrite.vert.spv and /dev/null differ diff --git a/shaders/hlsl/instancing/instancing.frag b/shaders/hlsl/instancing/instancing.frag deleted file mode 100644 index 1e3a0b78..00000000 --- a/shaders/hlsl/instancing/instancing.frag +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2DArray textureArray : register(t1); -SamplerState samplerArray : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureArray.Sample(samplerArray, input.UV) * float4(input.Color, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.1) * input.Color; - float3 specular = (dot(N,L) > 0.0) ? pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75) * color.r : float3(0.0, 0.0, 0.0); - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/instancing/instancing.frag.spv b/shaders/hlsl/instancing/instancing.frag.spv deleted file mode 100644 index 76c4aab3..00000000 Binary files a/shaders/hlsl/instancing/instancing.frag.spv and /dev/null differ diff --git a/shaders/hlsl/instancing/instancing.vert b/shaders/hlsl/instancing/instancing.vert deleted file mode 100644 index 62e41234..00000000 --- a/shaders/hlsl/instancing/instancing.vert +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; - -// Instanced attributes -[[vk::location(4)]] float3 instancePos : POSITION1; -[[vk::location(5)]] float3 instanceRot : TEXCOORD1; -[[vk::location(6)]] float instanceScale : TEXCOORD2; -[[vk::location(7)]] int instanceTexIndex : TEXCOORD3; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; - float locSpeed; - float globSpeed; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.UV = float3(input.UV, input.instanceTexIndex); - - // rotate around x - float s = sin(input.instanceRot.x + ubo.locSpeed); - float c = cos(input.instanceRot.x + ubo.locSpeed); - - float3x3 mx = { c, -s, 0.0, - s, c, 0.0, - 0.0, 0.0, 1.0 }; - - // rotate around y - s = sin(input.instanceRot.y + ubo.locSpeed); - c = cos(input.instanceRot.y + ubo.locSpeed); - - float3x3 my = { c, 0.0, -s, - 0.0, 1.0, 0.0, - s, 0.0, c }; - - // rot around z - s = sin(input.instanceRot.z + ubo.locSpeed); - c = cos(input.instanceRot.z + ubo.locSpeed); - - float3x3 mz = { 1.0, 0.0, 0.0, - 0.0, c, -s, - 0.0, s, c }; - - float3x3 rotMat = mul(mz, mul(my, mx)); - - float4x4 gRotMat; - s = sin(input.instanceRot.y + ubo.globSpeed); - c = cos(input.instanceRot.y + ubo.globSpeed); - gRotMat[0] = float4(c, 0.0, -s, 0.0); - gRotMat[1] = float4(0.0, 1.0, 0.0, 0.0); - gRotMat[2] = float4(s, 0.0, c, 0.0); - gRotMat[3] = float4(0.0, 0.0, 0.0, 1.0); - - float4 locPos = float4(mul(rotMat, input.Pos.xyz), 1.0); - float4 pos = float4((locPos.xyz * input.instanceScale) + input.instancePos, 1.0); - - output.Pos = mul(ubo.projection, mul(ubo.modelview, mul(gRotMat, pos))); - output.Normal = mul((float3x3)mul(ubo.modelview, gRotMat), mul(rotMat, input.Normal)); - - pos = mul(ubo.modelview, float4(input.Pos.xyz + input.instancePos, 1.0)); - float3 lPos = mul((float3x3)ubo.modelview, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} diff --git a/shaders/hlsl/instancing/instancing.vert.spv b/shaders/hlsl/instancing/instancing.vert.spv deleted file mode 100644 index cfd2b12e..00000000 Binary files a/shaders/hlsl/instancing/instancing.vert.spv and /dev/null differ diff --git a/shaders/hlsl/instancing/planet.frag b/shaders/hlsl/instancing/planet.frag deleted file mode 100644 index 8fca3642..00000000 --- a/shaders/hlsl/instancing/planet.frag +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0) * 1.5; - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 4.0) * float3(0.5, 0.5, 0.5) * color.r; - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/instancing/planet.frag.spv b/shaders/hlsl/instancing/planet.frag.spv deleted file mode 100644 index a768f1b2..00000000 Binary files a/shaders/hlsl/instancing/planet.frag.spv and /dev/null differ diff --git a/shaders/hlsl/instancing/planet.vert b/shaders/hlsl/instancing/planet.vert deleted file mode 100644 index 0be1e34e..00000000 --- a/shaders/hlsl/instancing/planet.vert +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.modelview, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.modelview, input.Normal); - float3 lPos = mul((float3x3)ubo.modelview, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/instancing/planet.vert.spv b/shaders/hlsl/instancing/planet.vert.spv deleted file mode 100644 index 4da7e547..00000000 Binary files a/shaders/hlsl/instancing/planet.vert.spv and /dev/null differ diff --git a/shaders/hlsl/instancing/starfield.frag b/shaders/hlsl/instancing/starfield.frag deleted file mode 100644 index a32fbaae..00000000 --- a/shaders/hlsl/instancing/starfield.frag +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 Google LLC - -#define HASHSCALE3 float3(443.897, 441.423, 437.195) -#define STARFREQUENCY 0.01 - -// Hash function by Dave Hoskins (https://www.shadertoy.com/view/4djSRW) -float hash33(float3 p3) -{ - p3 = frac(p3 * HASHSCALE3); - p3 += dot(p3, p3.yxz+float3(19.19, 19.19, 19.19)); - return frac((p3.x + p3.y)*p3.z + (p3.x+p3.z)*p3.y + (p3.y+p3.z)*p3.x); -} - -float3 starField(float3 pos) -{ - float3 color = float3(0.0, 0.0, 0.0); - float threshhold = (1.0 - STARFREQUENCY); - float rnd = hash33(pos); - if (rnd >= threshhold) - { - float starCol = pow((rnd - threshhold) / (1.0 - threshhold), 16.0); - color += starCol.xxx; - } - return color; -} - -float4 main([[vk::location(0)]] float3 inUVW : TEXCOORD0) : SV_TARGET -{ - return float4(starField(inUVW), 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/instancing/starfield.frag.spv b/shaders/hlsl/instancing/starfield.frag.spv deleted file mode 100644 index 594b95e8..00000000 Binary files a/shaders/hlsl/instancing/starfield.frag.spv and /dev/null differ diff --git a/shaders/hlsl/instancing/starfield.vert b/shaders/hlsl/instancing/starfield.vert deleted file mode 100644 index cb7a40d2..00000000 --- a/shaders/hlsl/instancing/starfield.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UVW : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UVW = float3((VertexIndex << 1) & 2, VertexIndex & 2, VertexIndex & 2); - output.Pos = float4(output.UVW.xy * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/instancing/starfield.vert.spv b/shaders/hlsl/instancing/starfield.vert.spv deleted file mode 100644 index 48afecac..00000000 Binary files a/shaders/hlsl/instancing/starfield.vert.spv and /dev/null differ diff --git a/shaders/hlsl/mesh/mesh.frag b/shaders/hlsl/mesh/mesh.frag deleted file mode 100644 index 2bc0a9c2..00000000 --- a/shaders/hlsl/mesh/mesh.frag +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/mesh/mesh.frag.spv b/shaders/hlsl/mesh/mesh.frag.spv deleted file mode 100644 index b7626a88..00000000 Binary files a/shaders/hlsl/mesh/mesh.frag.spv and /dev/null differ diff --git a/shaders/hlsl/mesh/mesh.vert b/shaders/hlsl/mesh/mesh.vert deleted file mode 100644 index 2ea7b03b..00000000 --- a/shaders/hlsl/mesh/mesh.vert +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/mesh/mesh.vert.spv b/shaders/hlsl/mesh/mesh.vert.spv deleted file mode 100644 index 38769e28..00000000 Binary files a/shaders/hlsl/mesh/mesh.vert.spv and /dev/null differ diff --git a/shaders/hlsl/meshshader/meshshader.frag b/shaders/hlsl/meshshader/meshshader.frag deleted file mode 100644 index d4e1e8de..00000000 --- a/shaders/hlsl/meshshader/meshshader.frag +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ -[[vk::location(0)]] float4 color : COLOR0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - return float4(input.color); -} \ No newline at end of file diff --git a/shaders/hlsl/meshshader/meshshader.frag.spv b/shaders/hlsl/meshshader/meshshader.frag.spv deleted file mode 100644 index 6c534184..00000000 Binary files a/shaders/hlsl/meshshader/meshshader.frag.spv and /dev/null differ diff --git a/shaders/hlsl/meshshader/meshshader.mesh b/shaders/hlsl/meshshader/meshshader.mesh deleted file mode 100644 index 840e009b..00000000 --- a/shaders/hlsl/meshshader/meshshader.mesh +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VertexOutput -{ - float4 position: SV_Position; - float4 color: COLOR0; -}; - -static const float4 positions[3] = { - float4( 0.0, -1.0, 0.0, 1.0), - float4(-1.0, 1.0, 0.0, 1.0), - float4( 1.0, 1.0, 0.0, 1.0) -}; - -static const float4 colors[3] = { - float4(0.0, 1.0, 0.0, 1.0), - float4(0.0, 0.0, 1.0, 1.0), - float4(1.0, 0.0, 0.0, 1.0) -}; - -[outputtopology("triangle")] -[numthreads(1, 1, 1)] -void main(out indices uint3 triangles[1], out vertices VertexOutput vertices[3], uint3 DispatchThreadID : SV_DispatchThreadID) -{ - float4x4 mvp = mul(ubo.projection, mul(ubo.view, ubo.model)); - - float4 offset = float4(0.0, 0.0, (float)DispatchThreadID, 0.0); - - SetMeshOutputCounts(3, 1); - for (uint i = 0; i < 3; i++) { - vertices[i].position = mul(mvp, positions[i] + offset); - vertices[i].color = colors[i]; - } - - SetMeshOutputCounts(3, 1); - triangles[0] = uint3(0, 1, 2); -} diff --git a/shaders/hlsl/meshshader/meshshader.mesh.spv b/shaders/hlsl/meshshader/meshshader.mesh.spv deleted file mode 100644 index e29bbb2c..00000000 Binary files a/shaders/hlsl/meshshader/meshshader.mesh.spv and /dev/null differ diff --git a/shaders/hlsl/meshshader/meshshader.task b/shaders/hlsl/meshshader/meshshader.task deleted file mode 100644 index 3b3b524e..00000000 --- a/shaders/hlsl/meshshader/meshshader.task +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (c) 2023, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct DummyPayLoad -{ - uint dummyData; -}; - -// We don't use pay loads in this sample, but the fn call requires one -groupshared DummyPayLoad dummyPayLoad; - -[numthreads(1,1,1)] -void main() -{ - DispatchMesh(3, 1, 1, dummyPayLoad); -} diff --git a/shaders/hlsl/meshshader/meshshader.task.spv b/shaders/hlsl/meshshader/meshshader.task.spv deleted file mode 100644 index 62823391..00000000 Binary files a/shaders/hlsl/meshshader/meshshader.task.spv and /dev/null differ diff --git a/shaders/hlsl/multisampling/mesh.frag b/shaders/hlsl/multisampling/mesh.frag deleted file mode 100644 index 273dde58..00000000 --- a/shaders/hlsl/multisampling/mesh.frag +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t0, space1); -SamplerState samplerColorMap : register(s0, space1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.15) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/multisampling/mesh.frag.spv b/shaders/hlsl/multisampling/mesh.frag.spv deleted file mode 100644 index d52870a3..00000000 Binary files a/shaders/hlsl/multisampling/mesh.frag.spv and /dev/null differ diff --git a/shaders/hlsl/multisampling/mesh.vert b/shaders/hlsl/multisampling/mesh.vert deleted file mode 100644 index 4e5e9f4e..00000000 --- a/shaders/hlsl/multisampling/mesh.vert +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 0.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - input.Pos; - output.ViewVec = -input.Pos; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/multisampling/mesh.vert.spv b/shaders/hlsl/multisampling/mesh.vert.spv deleted file mode 100644 index 96af4636..00000000 Binary files a/shaders/hlsl/multisampling/mesh.vert.spv and /dev/null differ diff --git a/shaders/hlsl/multithreading/phong.frag b/shaders/hlsl/multithreading/phong.frag deleted file mode 100644 index 5212cd15..00000000 --- a/shaders/hlsl/multithreading/phong.frag +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/multithreading/phong.frag.spv b/shaders/hlsl/multithreading/phong.frag.spv deleted file mode 100644 index 2990c679..00000000 Binary files a/shaders/hlsl/multithreading/phong.frag.spv and /dev/null differ diff --git a/shaders/hlsl/multithreading/phong.vert b/shaders/hlsl/multithreading/phong.vert deleted file mode 100644 index 1487ba17..00000000 --- a/shaders/hlsl/multithreading/phong.vert +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct PushConsts -{ - float4x4 mvp; - float3 color; -}; -[[vk::push_constant]]PushConsts pushConsts; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - - if ( (input.Color.r == 1.0) && (input.Color.g == 0.0) && (input.Color.b == 0.0)) - { - output.Color = pushConsts.color; - } - else - { - output.Color = input.Color; - } - - output.Pos = mul(pushConsts.mvp, float4(input.Pos.xyz, 1.0)); - - float4 pos = mul(pushConsts.mvp, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)pushConsts.mvp, input.Normal); -// float3 lPos = ubo.lightPos.xyz; -float3 lPos = float3(0.0, 0.0, 0.0); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/multithreading/phong.vert.spv b/shaders/hlsl/multithreading/phong.vert.spv deleted file mode 100644 index b5fd2a30..00000000 Binary files a/shaders/hlsl/multithreading/phong.vert.spv and /dev/null differ diff --git a/shaders/hlsl/multithreading/starsphere.frag b/shaders/hlsl/multithreading/starsphere.frag deleted file mode 100644 index aedb7e1d..00000000 --- a/shaders/hlsl/multithreading/starsphere.frag +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC - -#define HASHSCALE3 float3(443.897, 441.423, 437.195) -#define STARFREQUENCY 0.01 - -// Hash function by Dave Hoskins (https://www.shadertoy.com/view/4djSRW) -float hash33(float3 p3) -{ - p3 = frac(p3 * HASHSCALE3); - p3 += dot(p3, p3.yxz+float3(19.19, 19.19, 19.19)); - return frac((p3.x + p3.y)*p3.z + (p3.x+p3.z)*p3.y + (p3.y+p3.z)*p3.x); -} - -float3 starField(float3 pos) -{ - float3 color = float3(0.0, 0.0, 0.0); - float threshhold = (1.0 - STARFREQUENCY); - float rnd = hash33(pos); - if (rnd >= threshhold) - { - float starCol = pow((rnd - threshhold) / (1.0 - threshhold), 16.0); - color += starCol.xxx; - } - return color; -} - -float4 main([[vk::location(0)]] float3 inUVW : TEXCOORD0) : SV_TARGET -{ - // Fake atmosphere at the bottom - float3 atmosphere = clamp(float3(0.1, 0.15, 0.4) * (inUVW.y + 0.25), 0.0, 1.0); - - float3 color = starField(inUVW) + atmosphere; - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/multithreading/starsphere.frag.spv b/shaders/hlsl/multithreading/starsphere.frag.spv deleted file mode 100644 index 6a5eddc3..00000000 Binary files a/shaders/hlsl/multithreading/starsphere.frag.spv and /dev/null differ diff --git a/shaders/hlsl/multithreading/starsphere.vert b/shaders/hlsl/multithreading/starsphere.vert deleted file mode 100644 index 13e48cb2..00000000 --- a/shaders/hlsl/multithreading/starsphere.vert +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -struct PushConsts -{ - float4x4 mvp; -}; -[[vk::push_constant]]PushConsts pushConsts; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UVW : TEXCOORD0; -}; - -VSOutput main([[vk::location(0)]] float3 Pos : POSITION0) -{ - VSOutput output = (VSOutput)0; - output.UVW = Pos; - output.Pos = mul(pushConsts.mvp, float4(Pos.xyz, 1.0)); - return output; -} diff --git a/shaders/hlsl/multithreading/starsphere.vert.spv b/shaders/hlsl/multithreading/starsphere.vert.spv deleted file mode 100644 index 815e7257..00000000 Binary files a/shaders/hlsl/multithreading/starsphere.vert.spv and /dev/null differ diff --git a/shaders/hlsl/multiview/multiview.frag b/shaders/hlsl/multiview/multiview.frag deleted file mode 100644 index 2c14be89..00000000 --- a/shaders/hlsl/multiview/multiview.frag +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.1, 0.1, 0.1); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/multiview/multiview.frag.spv b/shaders/hlsl/multiview/multiview.frag.spv deleted file mode 100644 index 6966e9ad..00000000 Binary files a/shaders/hlsl/multiview/multiview.frag.spv and /dev/null differ diff --git a/shaders/hlsl/multiview/multiview.vert b/shaders/hlsl/multiview/multiview.vert deleted file mode 100644 index 214db9cf..00000000 --- a/shaders/hlsl/multiview/multiview.vert +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -struct UBO -{ - float4x4 projection[2]; - float4x4 modelview[2]; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -VSOutput main(VSInput input, uint ViewIndex : SV_ViewID) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Normal = mul((float3x3)ubo.modelview[ViewIndex], input.Normal); - - float4 pos = float4(input.Pos.xyz, 1.0); - float4 worldPos = mul(ubo.modelview[ViewIndex], pos); - - float3 lPos = mul(ubo.modelview[ViewIndex], ubo.lightPos).xyz; - output.LightVec = lPos - worldPos.xyz; - output.ViewVec = -worldPos.xyz; - - output.Pos = mul(ubo.projection[ViewIndex], worldPos); - return output; -} diff --git a/shaders/hlsl/multiview/multiview.vert.spv b/shaders/hlsl/multiview/multiview.vert.spv deleted file mode 100644 index 54de0603..00000000 Binary files a/shaders/hlsl/multiview/multiview.vert.spv and /dev/null differ diff --git a/shaders/hlsl/multiview/viewdisplay.frag b/shaders/hlsl/multiview/viewdisplay.frag deleted file mode 100644 index da365d00..00000000 --- a/shaders/hlsl/multiview/viewdisplay.frag +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2DArray textureView : register(t1); -SamplerState samplerView : register(s1); - -struct UBO -{ - [[vk::offset(272)]] float distortionAlpha; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -[[vk::constant_id(0)]] const float VIEW_LAYER = 0.0f; - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - const float alpha = ubo.distortionAlpha; - - float2 p1 = float2(2.0 * inUV - 1.0); - float2 p2 = p1 / (1.0 - alpha * length(p1)); - p2 = (p2 + 1.0) * 0.5; - - bool inside = ((p2.x >= 0.0) && (p2.x <= 1.0) && (p2.y >= 0.0 ) && (p2.y <= 1.0)); - return inside ? textureView.Sample(samplerView, float3(p2, VIEW_LAYER)) : float4(0.0, 0.0, 0.0, 0.0); -} \ No newline at end of file diff --git a/shaders/hlsl/multiview/viewdisplay.frag.spv b/shaders/hlsl/multiview/viewdisplay.frag.spv deleted file mode 100644 index 59d1aa29..00000000 Binary files a/shaders/hlsl/multiview/viewdisplay.frag.spv and /dev/null differ diff --git a/shaders/hlsl/multiview/viewdisplay.vert b/shaders/hlsl/multiview/viewdisplay.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/multiview/viewdisplay.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/multiview/viewdisplay.vert.spv b/shaders/hlsl/multiview/viewdisplay.vert.spv deleted file mode 100644 index 46c4b31f..00000000 Binary files a/shaders/hlsl/multiview/viewdisplay.vert.spv and /dev/null differ diff --git a/shaders/hlsl/negativeviewportheight/quad.frag b/shaders/hlsl/negativeviewportheight/quad.frag deleted file mode 100644 index 8236872c..00000000 --- a/shaders/hlsl/negativeviewportheight/quad.frag +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t0); -SamplerState samplerColor : register(s0); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - return textureColor.Sample(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/hlsl/negativeviewportheight/quad.frag.spv b/shaders/hlsl/negativeviewportheight/quad.frag.spv deleted file mode 100644 index 6247b5ff..00000000 Binary files a/shaders/hlsl/negativeviewportheight/quad.frag.spv and /dev/null differ diff --git a/shaders/hlsl/negativeviewportheight/quad.vert b/shaders/hlsl/negativeviewportheight/quad.vert deleted file mode 100644 index 1864c0be..00000000 --- a/shaders/hlsl/negativeviewportheight/quad.vert +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - output.Pos = float4(input.Pos, 1.0f); - return output; -} diff --git a/shaders/hlsl/negativeviewportheight/quad.vert.spv b/shaders/hlsl/negativeviewportheight/quad.vert.spv deleted file mode 100644 index 2e4b9563..00000000 Binary files a/shaders/hlsl/negativeviewportheight/quad.vert.spv and /dev/null differ diff --git a/shaders/hlsl/occlusionquery/mesh.frag b/shaders/hlsl/occlusionquery/mesh.frag deleted file mode 100644 index 9347ed10..00000000 --- a/shaders/hlsl/occlusionquery/mesh.frag +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float Visible : TEXCOORD3; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - if (input.Visible > 0.0) - { - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse + specular, 1.0); - } - else - { - return float4(float3(0.1, 0.1, 0.1), 1.0); - } -} \ No newline at end of file diff --git a/shaders/hlsl/occlusionquery/mesh.frag.spv b/shaders/hlsl/occlusionquery/mesh.frag.spv deleted file mode 100644 index 6c02ae55..00000000 Binary files a/shaders/hlsl/occlusionquery/mesh.frag.spv and /dev/null differ diff --git a/shaders/hlsl/occlusionquery/mesh.vert b/shaders/hlsl/occlusionquery/mesh.vert deleted file mode 100644 index 4b20662a..00000000 --- a/shaders/hlsl/occlusionquery/mesh.vert +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; - float visible; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float Visible : TEXCOORD3; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.Visible = ubo.visible; - - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.modelview, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.modelview, input.Normal); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/occlusionquery/mesh.vert.spv b/shaders/hlsl/occlusionquery/mesh.vert.spv deleted file mode 100644 index 5329a260..00000000 Binary files a/shaders/hlsl/occlusionquery/mesh.vert.spv and /dev/null differ diff --git a/shaders/hlsl/occlusionquery/occluder.frag b/shaders/hlsl/occlusionquery/occluder.frag deleted file mode 100644 index e18b7b33..00000000 --- a/shaders/hlsl/occlusionquery/occluder.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main([[vk::location(0)]] float3 Color : COLOR0) : SV_TARGET -{ - return float4(Color, 0.5); -} \ No newline at end of file diff --git a/shaders/hlsl/occlusionquery/occluder.frag.spv b/shaders/hlsl/occlusionquery/occluder.frag.spv deleted file mode 100644 index 2325bb39..00000000 Binary files a/shaders/hlsl/occlusionquery/occluder.frag.spv and /dev/null differ diff --git a/shaders/hlsl/occlusionquery/occluder.vert b/shaders/hlsl/occlusionquery/occluder.vert deleted file mode 100644 index dce12c8a..00000000 --- a/shaders/hlsl/occlusionquery/occluder.vert +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(input.Pos.xyz, 1.0))); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/occlusionquery/occluder.vert.spv b/shaders/hlsl/occlusionquery/occluder.vert.spv deleted file mode 100644 index ef0a4708..00000000 Binary files a/shaders/hlsl/occlusionquery/occluder.vert.spv and /dev/null differ diff --git a/shaders/hlsl/occlusionquery/simple.frag b/shaders/hlsl/occlusionquery/simple.frag deleted file mode 100644 index a898835c..00000000 --- a/shaders/hlsl/occlusionquery/simple.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main([[vk::location(0)]] float3 Color : COLOR0) : SV_TARGET -{ - return float4(1.0, 1.0, 1.0, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/occlusionquery/simple.frag.spv b/shaders/hlsl/occlusionquery/simple.frag.spv deleted file mode 100644 index 47bfe270..00000000 Binary files a/shaders/hlsl/occlusionquery/simple.frag.spv and /dev/null differ diff --git a/shaders/hlsl/occlusionquery/simple.vert b/shaders/hlsl/occlusionquery/simple.vert deleted file mode 100644 index 1618e05b..00000000 --- a/shaders/hlsl/occlusionquery/simple.vert +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2020 Google LLC - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -}; - -VSOutput main([[vk::location(0)]] float3 Pos : POSITION0) -{ - VSOutput output = (VSOutput)0; - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(Pos.xyz, 1.0))); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/occlusionquery/simple.vert.spv b/shaders/hlsl/occlusionquery/simple.vert.spv deleted file mode 100644 index 2756aede..00000000 Binary files a/shaders/hlsl/occlusionquery/simple.vert.spv and /dev/null differ diff --git a/shaders/hlsl/offscreen/mirror.frag b/shaders/hlsl/offscreen/mirror.frag deleted file mode 100644 index 72a3aa73..00000000 --- a/shaders/hlsl/offscreen/mirror.frag +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float4 ProjCoord : POSITION0; -}; - -float4 main(VSOutput input, bool FrontFacing : SV_IsFrontFace) : SV_TARGET -{ - float4 tmp = (1.0 / input.ProjCoord.w).xxxx; - float4 projCoord = input.ProjCoord * tmp; - - // Scale and bias - projCoord += float4(1.0, 1.0, 1.0, 1.0); - projCoord *= float4(0.5, 0.5, 0.5, 0.5); - - // Slow single pass blur - // For demonstration purposes only - const float blurSize = 1.0 / 512.0; - - float4 color = float4(float3(0.0, 0.0, 0.0), 1.); - - if (FrontFacing) - { - // Only render mirrored scene on front facing (upper) side of mirror surface - float4 reflection = float4(0.0, 0.0, 0.0, 0.0); - for (int x = -3; x <= 3; x++) - { - for (int y = -3; y <= 3; y++) - { - reflection += textureColor.Sample(samplerColor, float2(projCoord.x + x * blurSize, projCoord.y + y * blurSize)) / 49.0; - } - } - color += reflection; - } - - return color; -} \ No newline at end of file diff --git a/shaders/hlsl/offscreen/mirror.frag.spv b/shaders/hlsl/offscreen/mirror.frag.spv deleted file mode 100644 index ff33a17b..00000000 Binary files a/shaders/hlsl/offscreen/mirror.frag.spv and /dev/null differ diff --git a/shaders/hlsl/offscreen/mirror.vert b/shaders/hlsl/offscreen/mirror.vert deleted file mode 100644 index f7c547eb..00000000 --- a/shaders/hlsl/offscreen/mirror.vert +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float4 ProjCoord : POSITION0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.ProjCoord = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - output.Pos = output.ProjCoord; - return output; -} diff --git a/shaders/hlsl/offscreen/mirror.vert.spv b/shaders/hlsl/offscreen/mirror.vert.spv deleted file mode 100644 index 83e55df2..00000000 Binary files a/shaders/hlsl/offscreen/mirror.vert.spv and /dev/null differ diff --git a/shaders/hlsl/offscreen/phong.frag b/shaders/hlsl/offscreen/phong.frag deleted file mode 100644 index 62c69695..00000000 --- a/shaders/hlsl/offscreen/phong.frag +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 EyePos : POSITION0; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - - float4 IAmbient = float4(0.1, 0.1, 0.1, 1.0); - float4 IDiffuse = max(dot(input.Normal, input.LightVec), 0.0).xxxx; - float specular = 0.75; - float4 ISpecular = float4(0.0, 0.0, 0.0, 0.0); - if (dot(input.EyePos, input.Normal) < 0.0) - { - ISpecular = float4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 16.0) * specular; - } - - return float4((IAmbient + IDiffuse) * float4(input.Color, 1.0) + ISpecular); -} \ No newline at end of file diff --git a/shaders/hlsl/offscreen/phong.frag.spv b/shaders/hlsl/offscreen/phong.frag.spv deleted file mode 100644 index 6dbb9936..00000000 Binary files a/shaders/hlsl/offscreen/phong.frag.spv and /dev/null differ diff --git a/shaders/hlsl/offscreen/phong.vert b/shaders/hlsl/offscreen/phong.vert deleted file mode 100644 index 04f73c1a..00000000 --- a/shaders/hlsl/offscreen/phong.vert +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float ClipDistance : SV_ClipDistance0; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 EyePos : POSITION0; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos))); - output.EyePos = mul(ubo.view, mul(ubo.model, input.Pos)).xyz; - output.LightVec = normalize(ubo.lightPos.xyz - output.EyePos); - - // Clip against reflection plane - float4 clipPlane = float4(0.0, -1.0, 0.0, 0.0); - output.ClipDistance = dot(input.Pos, clipPlane); - return output; -} diff --git a/shaders/hlsl/offscreen/phong.vert.spv b/shaders/hlsl/offscreen/phong.vert.spv deleted file mode 100644 index 44b0e5c0..00000000 Binary files a/shaders/hlsl/offscreen/phong.vert.spv and /dev/null differ diff --git a/shaders/hlsl/offscreen/quad.frag b/shaders/hlsl/offscreen/quad.frag deleted file mode 100644 index 997a9419..00000000 --- a/shaders/hlsl/offscreen/quad.frag +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - return textureColor.Sample(samplerColor, inUV); -} \ No newline at end of file diff --git a/shaders/hlsl/offscreen/quad.frag.spv b/shaders/hlsl/offscreen/quad.frag.spv deleted file mode 100644 index 5a671efa..00000000 Binary files a/shaders/hlsl/offscreen/quad.frag.spv and /dev/null differ diff --git a/shaders/hlsl/offscreen/quad.vert b/shaders/hlsl/offscreen/quad.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/offscreen/quad.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/offscreen/quad.vert.spv b/shaders/hlsl/offscreen/quad.vert.spv deleted file mode 100644 index 8754eaa1..00000000 Binary files a/shaders/hlsl/offscreen/quad.vert.spv and /dev/null differ diff --git a/shaders/hlsl/oit/color.frag b/shaders/hlsl/oit/color.frag deleted file mode 100644 index d50c1150..00000000 --- a/shaders/hlsl/oit/color.frag +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2020 Sascha Willems - -#define MAX_FRAGMENT_COUNT 128 - -struct VSOutput -{ - float4 Pos : SV_POSITION; -}; - -struct Node -{ - float4 color; - float depth; - uint next; -}; - -RWTexture2D headIndexImage : register(u0); - -struct Particle -{ - float2 pos; - float2 vel; - float4 gradientPos; -}; - -// Binding 0 : Position storage buffer -RWStructuredBuffer nodes : register(u1); - -float4 main(VSOutput input) : SV_TARGET -{ - Node fragments[MAX_FRAGMENT_COUNT]; - int count = 0; - - uint nodeIdx = headIndexImage[uint2(input.Pos.xy)].r; - - while (nodeIdx != 0xffffffff && count < MAX_FRAGMENT_COUNT) - { - fragments[count] = nodes[nodeIdx]; - nodeIdx = fragments[count].next; - ++count; - } - - // Do the insertion sort - for (uint i = 1; i < count; ++i) - { - Node insert = fragments[i]; - uint j = i; - while (j > 0 && insert.depth > fragments[j - 1].depth) - { - fragments[j] = fragments[j-1]; - --j; - } - fragments[j] = insert; - } - - // Do blending - float4 color = float4(0.025, 0.025, 0.025, 1.0f); - for (uint f = 0; f < count; ++f) - { - color = lerp(color, fragments[f].color, fragments[f].color.a); - } - - return color; -} \ No newline at end of file diff --git a/shaders/hlsl/oit/color.frag.spv b/shaders/hlsl/oit/color.frag.spv deleted file mode 100644 index 7e2e62e9..00000000 Binary files a/shaders/hlsl/oit/color.frag.spv and /dev/null differ diff --git a/shaders/hlsl/oit/color.vert b/shaders/hlsl/oit/color.vert deleted file mode 100644 index 609b3606..00000000 --- a/shaders/hlsl/oit/color.vert +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2020 Sascha Willems - -struct VSOutput -{ - float4 Pos : SV_POSITION; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - float2 UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/oit/color.vert.spv b/shaders/hlsl/oit/color.vert.spv deleted file mode 100644 index 03158809..00000000 Binary files a/shaders/hlsl/oit/color.vert.spv and /dev/null differ diff --git a/shaders/hlsl/oit/geometry.frag b/shaders/hlsl/oit/geometry.frag deleted file mode 100644 index 2a997a94..00000000 --- a/shaders/hlsl/oit/geometry.frag +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2020 Sascha Willems - -struct VSOutput -{ - float4 Pos : SV_POSITION; -}; - -struct Node -{ - float4 color; - float depth; - uint next; -}; - -struct GeometrySBO -{ - uint count; - uint maxNodeCount; -}; -// Binding 0 : Position storage buffer -RWStructuredBuffer geometrySBO : register(u1); - -RWTexture2D headIndexImage : register(u2); - -RWStructuredBuffer nodes : register(u3); - -struct PushConsts { - float4x4 model; - float4 color; -}; -[[vk::push_constant]] PushConsts pushConsts; - -[earlydepthstencil] -void main(VSOutput input) -{ - // Increase the node count - uint nodeIdx; - InterlockedAdd(geometrySBO[0].count, 1, nodeIdx); - - // Check LinkedListSBO is full - if (nodeIdx < geometrySBO[0].maxNodeCount) - { - // Exchange new head index and previous head index - uint prevHeadIdx; - InterlockedExchange(headIndexImage[uint2(input.Pos.xy)], nodeIdx, prevHeadIdx); - - // Store node data - nodes[nodeIdx].color = pushConsts.color; - nodes[nodeIdx].depth = input.Pos.z; - nodes[nodeIdx].next = prevHeadIdx; - } -} \ No newline at end of file diff --git a/shaders/hlsl/oit/geometry.frag.spv b/shaders/hlsl/oit/geometry.frag.spv deleted file mode 100644 index 01fd554d..00000000 Binary files a/shaders/hlsl/oit/geometry.frag.spv and /dev/null differ diff --git a/shaders/hlsl/oit/geometry.vert b/shaders/hlsl/oit/geometry.vert deleted file mode 100644 index c1d114f3..00000000 --- a/shaders/hlsl/oit/geometry.vert +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2020 Sascha Willems - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -}; - -struct RenderPassUBO -{ - float4x4 projection; - float4x4 view; -}; - -cbuffer renderPassUBO : register(b0) { RenderPassUBO renderPassUBO; } - -struct PushConsts { - float4x4 model; - float4 color; -}; -[[vk::push_constant]] PushConsts pushConsts; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = mul(renderPassUBO.projection, mul(renderPassUBO.view, mul(pushConsts.model, input.Pos))); - return output; -} diff --git a/shaders/hlsl/oit/geometry.vert.spv b/shaders/hlsl/oit/geometry.vert.spv deleted file mode 100644 index d7b08261..00000000 Binary files a/shaders/hlsl/oit/geometry.vert.spv and /dev/null differ diff --git a/shaders/hlsl/parallaxmapping/parallax.frag b/shaders/hlsl/parallaxmapping/parallax.frag deleted file mode 100644 index 9451471b..00000000 --- a/shaders/hlsl/parallaxmapping/parallax.frag +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); -Texture2D textureNormalHeightMap : register(t2); -SamplerState samplerNormalHeightMap : register(s2); - -struct UBO -{ - float heightScale; - float parallaxBias; - float numLayers; - int mappingMode; -}; - -cbuffer ubo : register(b3) { UBO ubo; } - -struct VSOutput -{ -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float3 TangentLightPos : TEXCOORD1; -[[vk::location(2)]] float3 TangentViewPos : TEXCOORD2; -[[vk::location(3)]] float3 TangentFragPos : TEXCOORD3; -}; - -float2 parallaxMapping(float2 uv, float3 viewDir) -{ - float height = 1.0 - textureNormalHeightMap.SampleLevel(samplerNormalHeightMap, uv, 0.0).a; - float2 p = viewDir.xy * (height * (ubo.heightScale * 0.5) + ubo.parallaxBias) / viewDir.z; - return uv - p; -} - -float2 steepParallaxMapping(float2 uv, float3 viewDir) -{ - float layerDepth = 1.0 / ubo.numLayers; - float currLayerDepth = 0.0; - float2 deltaUV = viewDir.xy * ubo.heightScale / (viewDir.z * ubo.numLayers); - float2 currUV = uv; - float height = 1.0 - textureNormalHeightMap.SampleLevel(samplerNormalHeightMap, currUV, 0.0).a; - for (int i = 0; i < ubo.numLayers; i++) { - currLayerDepth += layerDepth; - currUV -= deltaUV; - height = 1.0 - textureNormalHeightMap.SampleLevel(samplerNormalHeightMap, currUV, 0.0).a; - if (height < currLayerDepth) { - break; - } - } - return currUV; -} - -float2 parallaxOcclusionMapping(float2 uv, float3 viewDir) -{ - float layerDepth = 1.0 / ubo.numLayers; - float currLayerDepth = 0.0; - float2 deltaUV = viewDir.xy * ubo.heightScale / (viewDir.z * ubo.numLayers); - float2 currUV = uv; - float height = 1.0 - textureNormalHeightMap.SampleLevel(samplerNormalHeightMap, currUV, 0.0).a; - for (int i = 0; i < ubo.numLayers; i++) { - currLayerDepth += layerDepth; - currUV -= deltaUV; - height = 1.0 - textureNormalHeightMap.SampleLevel(samplerNormalHeightMap, currUV, 0.0).a; - if (height < currLayerDepth) { - break; - } - } - float2 prevUV = currUV + deltaUV; - float nextDepth = height - currLayerDepth; - float prevDepth = 1.0 - textureNormalHeightMap.SampleLevel(samplerNormalHeightMap, prevUV, 0.0).a - currLayerDepth + layerDepth; - return lerp(currUV, prevUV, nextDepth / (nextDepth - prevDepth)); -} - -float4 main(VSOutput input) : SV_TARGET -{ - float3 V = normalize(input.TangentViewPos - input.TangentFragPos); - float2 uv = input.UV; - - if (ubo.mappingMode == 0) { - // Color only - return textureColorMap.Sample(samplerColorMap, input.UV); - } else { - switch(ubo.mappingMode) { - case 2: - uv = parallaxMapping(input.UV, V); - break; - case 3: - uv = steepParallaxMapping(input.UV, V); - break; - case 4: - uv = parallaxOcclusionMapping(input.UV, V); - break; - } - - // Discard fragments at texture border - if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) { - clip(-1); - } - - float3 N = normalize(textureNormalHeightMap.SampleLevel(samplerNormalHeightMap, uv, 0.0).rgb * 2.0 - 1.0); - float3 L = normalize(input.TangentLightPos - input.TangentFragPos); - float3 R = reflect(-L, N); - float3 H = normalize(L + V); - - float3 color = textureColorMap.Sample(samplerColorMap, uv).rgb; - float3 ambient = 0.2 * color; - float3 diffuse = max(dot(L, N), 0.0) * color; - float3 specular = float3(0.15, 0.15, 0.15) * pow(max(dot(N, H), 0.0), 32.0); - - return float4(ambient + diffuse + specular, 1.0f); - } -} diff --git a/shaders/hlsl/parallaxmapping/parallax.frag.spv b/shaders/hlsl/parallaxmapping/parallax.frag.spv deleted file mode 100644 index cd363d37..00000000 Binary files a/shaders/hlsl/parallaxmapping/parallax.frag.spv and /dev/null differ diff --git a/shaders/hlsl/parallaxmapping/parallax.vert b/shaders/hlsl/parallaxmapping/parallax.vert deleted file mode 100644 index 3328508f..00000000 --- a/shaders/hlsl/parallaxmapping/parallax.vert +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float4 Tangent : TEXCOORD1; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; - float4 cameraPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float3 TangentLightPos : TEXCOORD1; -[[vk::location(2)]] float3 TangentViewPos : TEXCOORD2; -[[vk::location(3)]] float3 TangentFragPos : TEXCOORD3; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos, 1.0f)))); - output.UV = input.UV; - - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent.xyz); - float3 B = normalize(cross(N, T)); - float3x3 TBN = float3x3(T, B, N); - - output.TangentLightPos = mul(TBN, ubo.lightPos.xyz); - output.TangentViewPos = mul(TBN, ubo.cameraPos.xyz); - output.TangentFragPos = mul(TBN, mul(ubo.model, float4(input.Pos, 1.0)).xyz); - return output; -} diff --git a/shaders/hlsl/parallaxmapping/parallax.vert.spv b/shaders/hlsl/parallaxmapping/parallax.vert.spv deleted file mode 100644 index 1ead6c4d..00000000 Binary files a/shaders/hlsl/parallaxmapping/parallax.vert.spv and /dev/null differ diff --git a/shaders/hlsl/particlesystem/normalmap.frag b/shaders/hlsl/particlesystem/normalmap.frag deleted file mode 100644 index 40ff7358..00000000 --- a/shaders/hlsl/particlesystem/normalmap.frag +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); -Texture2D textureNormalHeightMap : register(t2); -SamplerState samplerNormalHeightMap : register(s2); - -#define lightRadius 45.0 - -struct VSOutput -{ -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float3 LightVec : TEXCOORD2; -[[vk::location(2)]] float3 LightVecB : TEXCOORD3; -[[vk::location(3)]] float3 LightDir : TEXCOORD4; -[[vk::location(4)]] float3 ViewVec : TEXCOORD1; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 specularColor = float3(0.85, 0.5, 0.0); - - float invRadius = 1.0/lightRadius; - float ambient = 0.25; - - float3 rgb, normal; - - rgb = textureColorMap.Sample(samplerColorMap, input.UV).rgb; - normal = normalize((textureNormalHeightMap.Sample(samplerNormalHeightMap, input.UV).rgb - 0.5) * 2.0); - - float distSqr = dot(input.LightVecB, input.LightVecB); - float3 lVec = input.LightVecB * rsqrt(distSqr); - - float atten = max(clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0), ambient); - float diffuse = clamp(dot(lVec, normal), 0.0, 1.0); - - float3 light = normalize(-input.LightVec); - float3 view = normalize(input.ViewVec); - float3 reflectDir = reflect(-light, normal); - - float specular = pow(max(dot(view, reflectDir), 0.0), 4.0); - - return float4((rgb * atten + (diffuse * rgb + 0.5 * specular * specularColor.rgb)) * atten, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/particlesystem/normalmap.frag.spv b/shaders/hlsl/particlesystem/normalmap.frag.spv deleted file mode 100644 index 6b753f22..00000000 Binary files a/shaders/hlsl/particlesystem/normalmap.frag.spv and /dev/null differ diff --git a/shaders/hlsl/particlesystem/normalmap.vert b/shaders/hlsl/particlesystem/normalmap.vert deleted file mode 100644 index 7c36f723..00000000 --- a/shaders/hlsl/particlesystem/normalmap.vert +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float4 Tangent : TEXCOORD1; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 normal; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float3 LightVec : TEXCOORD2; -[[vk::location(2)]] float3 LightVecB : TEXCOORD3; -[[vk::location(3)]] float3 LightDir : TEXCOORD4; -[[vk::location(4)]] float3 ViewVec : TEXCOORD1; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - float3 vertexPosition = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.LightDir = normalize(ubo.lightPos.xyz - vertexPosition); - - float3 biTangent = cross(input.Normal, input.Tangent.xyz); - - // Setup (t)angent-(b)inormal-(n)ormal matrix for converting - // object coordinates into tangent space - float3x3 tbnMatrix; - tbnMatrix[0] = mul((float3x3)ubo.normal, input.Tangent); - tbnMatrix[1] = mul((float3x3)ubo.normal, biTangent); - tbnMatrix[2] = mul((float3x3)ubo.normal, input.Normal); - - output.LightVec.xyz = mul(float3(ubo.lightPos.xyz - vertexPosition), tbnMatrix); - - float3 lightDist = ubo.lightPos.xyz - input.Pos; - output.LightVecB.x = dot(input.Tangent, lightDist); - output.LightVecB.y = dot(biTangent, lightDist); - output.LightVecB.z = dot(input.Normal, lightDist); - - output.ViewVec.x = dot(input.Tangent, input.Pos); - output.ViewVec.y = dot(biTangent, input.Pos); - output.ViewVec.z = dot(input.Normal, input.Pos); - - output.UV = input.UV; - - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos, 1.0))); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/particlesystem/normalmap.vert.spv b/shaders/hlsl/particlesystem/normalmap.vert.spv deleted file mode 100644 index f0acd276..00000000 Binary files a/shaders/hlsl/particlesystem/normalmap.vert.spv and /dev/null differ diff --git a/shaders/hlsl/particlesystem/particle.frag b/shaders/hlsl/particlesystem/particle.frag deleted file mode 100644 index f2a7d375..00000000 --- a/shaders/hlsl/particlesystem/particle.frag +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureSmoke : register(t1); -SamplerState samplerSmoke : register(s1); -Texture2D textureFire : register(t2); -SamplerState samplerFire : register(s2); - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float4 Color : COLOR0; -[[vk::location(1)]] float Alpha : TEXCOODR0; -[[vk::location(2)]] int Type : TEXCOODR1; -[[vk::location(3)]] float Rotation : TEXCOODR2; -[[vk::location(4)]] float2 CenterPos : POSITION1; -[[vk::location(5)]] float PointSize : TEXCOORD3; -}; - -float4 main (VSOutput input) : SV_TARGET -{ - float4 color; - float alpha = (input.Alpha <= 1.0) ? input.Alpha : 2.0 - input.Alpha; - - // Rotate texture coordinates - // Rotate UV - float rotCenter = 0.5; - float rotCos = cos(input.Rotation); - float rotSin = sin(input.Rotation); - - float2 PointCoord = (input.Pos.xy - input.CenterPos.xy) / input.PointSize + 0.5; - - float2 rotUV = float2( - rotCos * (PointCoord.x - rotCenter) + rotSin * (PointCoord.y - rotCenter) + rotCenter, - rotCos * (PointCoord.y - rotCenter) - rotSin * (PointCoord.x - rotCenter) + rotCenter); - - float4 outFragColor; - if (input.Type == 0) - { - // Flame - color = textureFire.Sample(samplerFire, rotUV); - outFragColor.a = 0.0; - } - else - { - // Smoke - color = textureSmoke.Sample(samplerSmoke, rotUV); - outFragColor.a = color.a * alpha; - } - - outFragColor.rgb = color.rgb * input.Color.rgb * alpha; - return outFragColor; -} \ No newline at end of file diff --git a/shaders/hlsl/particlesystem/particle.frag.spv b/shaders/hlsl/particlesystem/particle.frag.spv deleted file mode 100644 index 294b2310..00000000 Binary files a/shaders/hlsl/particlesystem/particle.frag.spv and /dev/null differ diff --git a/shaders/hlsl/particlesystem/particle.vert b/shaders/hlsl/particlesystem/particle.vert deleted file mode 100644 index 30794139..00000000 --- a/shaders/hlsl/particlesystem/particle.vert +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float4 Color : COLOR0; -[[vk::location(2)]] float Alpha : TEXCOORD0; -[[vk::location(3)]] float Size : TEXCOORD1; -[[vk::location(4)]] float Rotation : TEXCOORD2; -[[vk::location(5)]] int Type : TEXCOORD3; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::builtin("PointSize")]] float PSize : PSIZE; -[[vk::location(0)]] float4 Color : COLOR0; -[[vk::location(1)]] float Alpha : TEXCOORD0; -[[vk::location(2)]] int Type : TEXCOORD1; -[[vk::location(3)]] float Rotation : TEXCOORD2; -[[vk::location(4)]] float2 CenterPos : POSITION1; -[[vk::location(5)]] float PointSize : TEXCOORD3; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float2 viewportDim; - float pointSize; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -VSOutput main (VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Alpha = input.Alpha; - output.Type = input.Type; - output.Rotation = input.Rotation; - - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(input.Pos.xyz, 1.0))); - - // Base size of the point sprites - float spriteSize = 8.0 * input.Size; - - // Scale particle size depending on camera projection - float4 eyePos = mul(ubo.modelview, float4(input.Pos.xyz, 1.0)); - float4 projectedCorner = mul(ubo.projection, float4(0.5 * spriteSize, 0.5 * spriteSize, eyePos.z, eyePos.w)); - output.PointSize = output.PSize = ubo.viewportDim.x * projectedCorner.x / projectedCorner.w; - output.CenterPos = ((output.Pos.xy / output.Pos.w) + 1.0) * 0.5 * ubo.viewportDim; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/particlesystem/particle.vert.spv b/shaders/hlsl/particlesystem/particle.vert.spv deleted file mode 100644 index ad0b55ed..00000000 Binary files a/shaders/hlsl/particlesystem/particle.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pbrbasic/pbr.frag b/shaders/hlsl/pbrbasic/pbr.frag deleted file mode 100644 index 55e89240..00000000 --- a/shaders/hlsl/pbrbasic/pbr.frag +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 WorldPos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct UBOShared { - float4 lights[4]; -}; - -cbuffer uboParams : register(b1) { UBOShared uboParams; }; - -struct PushConsts { -[[vk::offset(12)]] float roughness; -[[vk::offset(16)]] float metallic; -[[vk::offset(20)]] float r; -[[vk::offset(24)]] float g; -[[vk::offset(28)]] float b; -}; - -[[vk::push_constant]] PushConsts material; - -static const float PI = 3.14159265359; - -//#define ROUGHNESS_PATTERN 1 - -float3 materialcolor() -{ - return float3(material.r, material.g, material.b); -} - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -float3 F_Schlick(float cosTheta, float metallic) -{ - float3 F0 = lerp(float3(0.04, 0.04, 0.04), materialcolor(), metallic); // * material.specular - float3 F = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); - return F; -} - -// Specular BRDF composition -------------------------------------------- - -float3 BRDF(float3 L, float3 V, float3 N, float metallic, float roughness) -{ - // Precalculate vectors and dot products - float3 H = normalize (V + L); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - float dotLH = clamp(dot(L, H), 0.0, 1.0); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - - // Light color fixed - float3 lightColor = float3(1.0, 1.0, 1.0); - - float3 color = float3(0.0, 0.0, 0.0); - - if (dotNL > 0.0) - { - float rroughness = max(0.05, roughness); - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, roughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, rroughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - float3 F = F_Schlick(dotNV, metallic); - - float3 spec = D * F * G / (4.0 * dotNL * dotNV); - - color += spec * dotNL * lightColor; - } - - return color; -} - -// ---------------------------------------------------------------------------- -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 V = normalize(ubo.camPos - input.WorldPos); - - float roughness = material.roughness; - - // Add striped pattern to roughness based on vertex position -#ifdef ROUGHNESS_PATTERN - roughness = max(roughness, step(frac(input.WorldPos.y * 2.02), 0.5)); -#endif - - // Specular contribution - float3 Lo = float3(0.0, 0.0, 0.0); - for (int i = 0; i < 4; i++) { - float3 L = normalize(uboParams.lights[i].xyz - input.WorldPos); - Lo += BRDF(L, V, N, material.metallic, roughness); - }; - - // Combine with ambient - float3 color = materialcolor() * 0.02; - color += Lo; - - // Gamma correct - color = pow(color, float3(0.4545, 0.4545, 0.4545)); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/pbrbasic/pbr.frag.spv b/shaders/hlsl/pbrbasic/pbr.frag.spv deleted file mode 100644 index 1d4f7125..00000000 Binary files a/shaders/hlsl/pbrbasic/pbr.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbrbasic/pbr.vert b/shaders/hlsl/pbrbasic/pbr.vert deleted file mode 100644 index c53e7dbb..00000000 --- a/shaders/hlsl/pbrbasic/pbr.vert +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 WorldPos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -struct PushConsts { - float3 objPos; -}; -[[vk::push_constant]] PushConsts pushConsts; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - float3 locPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.WorldPos = locPos + pushConsts.objPos; - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.Pos = mul(ubo.projection, mul(ubo.view, float4(output.WorldPos, 1.0))); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/pbrbasic/pbr.vert.spv b/shaders/hlsl/pbrbasic/pbr.vert.spv deleted file mode 100644 index 06802f51..00000000 Binary files a/shaders/hlsl/pbrbasic/pbr.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pbribl/filtercube.vert b/shaders/hlsl/pbribl/filtercube.vert deleted file mode 100644 index 514b4dd2..00000000 --- a/shaders/hlsl/pbribl/filtercube.vert +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -}; - -struct PushConsts { -[[vk::offset(0)]] float4x4 mvp; -}; -[[vk::push_constant]] PushConsts pushConsts; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UVW : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UVW = input.Pos; - output.Pos = mul(pushConsts.mvp, float4(input.Pos.xyz, 1.0)); - return output; -} diff --git a/shaders/hlsl/pbribl/filtercube.vert.spv b/shaders/hlsl/pbribl/filtercube.vert.spv deleted file mode 100644 index 9b32c2dd..00000000 Binary files a/shaders/hlsl/pbribl/filtercube.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pbribl/genbrdflut.frag b/shaders/hlsl/pbribl/genbrdflut.frag deleted file mode 100644 index 64f325f7..00000000 --- a/shaders/hlsl/pbribl/genbrdflut.frag +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2020 Google LLC - -[[vk::constant_id(0)]] const uint NUM_SAMPLES = 1024u; - -#define PI 3.1415926536 - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(float2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,float2(a,b)); - float sn= fmod(dt,3.14); - return frac(sin(sn) * c); -} - -float2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return float2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -float3 importanceSample_GGX(float2 Xi, float roughness, float3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - float3 up = abs(normal.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); - float3 tangentX = normalize(cross(up, normal)); - float3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Geometric Shadowing function -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float k = (roughness * roughness) / 2.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -float2 BRDF(float NoV, float roughness) -{ - // Normal always points along z-axis for the 2D lookup - const float3 N = float3(0.0, 0.0, 1.0); - float3 V = float3(sqrt(1.0 - NoV*NoV), 0.0, NoV); - - float2 LUT = float2(0.0, 0.0); - for(uint i = 0u; i < NUM_SAMPLES; i++) { - float2 Xi = hammersley2d(i, NUM_SAMPLES); - float3 H = importanceSample_GGX(Xi, roughness, N); - float3 L = 2.0 * dot(V, H) * H - V; - - float dotNL = max(dot(N, L), 0.0); - float dotNV = max(dot(N, V), 0.0); - float dotVH = max(dot(V, H), 0.0); - float dotNH = max(dot(H, N), 0.0); - - if (dotNL > 0.0) { - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - float G_Vis = (G * dotVH) / (dotNH * dotNV); - float Fc = pow(1.0 - dotVH, 5.0); - LUT += float2((1.0 - Fc) * G_Vis, Fc * G_Vis); - } - } - return LUT / float(NUM_SAMPLES); -} - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - return float4(BRDF(inUV.x, inUV.y), 0.0, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/pbribl/genbrdflut.frag.spv b/shaders/hlsl/pbribl/genbrdflut.frag.spv deleted file mode 100644 index 899a81a5..00000000 Binary files a/shaders/hlsl/pbribl/genbrdflut.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbribl/genbrdflut.vert b/shaders/hlsl/pbribl/genbrdflut.vert deleted file mode 100644 index 188b7298..00000000 --- a/shaders/hlsl/pbribl/genbrdflut.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/pbribl/genbrdflut.vert.spv b/shaders/hlsl/pbribl/genbrdflut.vert.spv deleted file mode 100644 index 46c4b31f..00000000 Binary files a/shaders/hlsl/pbribl/genbrdflut.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pbribl/irradiancecube.frag b/shaders/hlsl/pbribl/irradiancecube.frag deleted file mode 100644 index 66d63bf6..00000000 --- a/shaders/hlsl/pbribl/irradiancecube.frag +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureEnv : register(t0); -SamplerState samplerEnv : register(s0); - -struct PushConsts { -[[vk::offset(64)]] float deltaPhi; -[[vk::offset(68)]] float deltaTheta; -}; -[[vk::push_constant]]PushConsts consts; - -#define PI 3.1415926535897932384626433832795 - -float4 main([[vk::location(0)]] float3 inPos : TEXCOORD0) : SV_TARGET -{ - float3 N = normalize(inPos); - float3 up = float3(0.0, 1.0, 0.0); - float3 right = normalize(cross(up, N)); - up = cross(N, right); - - const float TWO_PI = PI * 2.0; - const float HALF_PI = PI * 0.5; - - float3 color = float3(0.0, 0.0, 0.0); - uint sampleCount = 0u; - for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) { - for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) { - float3 tempVec = cos(phi) * right + sin(phi) * up; - float3 sampleVector = cos(theta) * N + sin(theta) * tempVec; - color += textureEnv.Sample(samplerEnv, sampleVector).rgb * cos(theta) * sin(theta); - sampleCount++; - } - } - return float4(PI * color / float(sampleCount), 1.0); -} diff --git a/shaders/hlsl/pbribl/irradiancecube.frag.spv b/shaders/hlsl/pbribl/irradiancecube.frag.spv deleted file mode 100644 index b3def200..00000000 Binary files a/shaders/hlsl/pbribl/irradiancecube.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbribl/pbribl.frag b/shaders/hlsl/pbribl/pbribl.frag deleted file mode 100644 index 4f135c4d..00000000 --- a/shaders/hlsl/pbribl/pbribl.frag +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 WorldPos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct UBO { - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct UBOParams { - float4 lights[4]; - float exposure; - float gamma; -}; -cbuffer uboParams : register(b1) { UBOParams uboParams; }; - -struct PushConsts { -[[vk::offset(12)]] float roughness; -[[vk::offset(16)]] float metallic; -[[vk::offset(20)]] float specular; -[[vk::offset(24)]] float r; -[[vk::offset(28)]] float g; -[[vk::offset(32)]] float b; -}; -[[vk::push_constant]] PushConsts material; - -TextureCube textureIrradiance : register(t2); -SamplerState samplerIrradiance : register(s2); -Texture2D textureBRDFLUT : register(t3); -SamplerState samplerBRDFLUT : register(s3); -TextureCube prefilteredMapTexture : register(t4); -SamplerState prefilteredMapSampler : register(s4); - -#define PI 3.1415926535897932384626433832795 -#define ALBEDO float3(material.r, material.g, material.b) - -// From http://filmicgames.com/archives/75 -float3 Uncharted2Tonemap(float3 x) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F; -} - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -float3 F_Schlick(float cosTheta, float3 F0) -{ - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} -float3 F_SchlickR(float cosTheta, float3 F0, float roughness) -{ - return F0 + (max((1.0 - roughness).xxx, F0) - F0) * pow(1.0 - cosTheta, 5.0); -} - -float3 prefilteredReflection(float3 R, float roughness) -{ - const float MAX_REFLECTION_LOD = 9.0; // todo: param/const - float lod = roughness * MAX_REFLECTION_LOD; - float lodf = floor(lod); - float lodc = ceil(lod); - float3 a = prefilteredMapTexture.SampleLevel(prefilteredMapSampler, R, lodf).rgb; - float3 b = prefilteredMapTexture.SampleLevel(prefilteredMapSampler, R, lodc).rgb; - return lerp(a, b, lod - lodf); -} - -float3 specularContribution(float3 L, float3 V, float3 N, float3 F0, float metallic, float roughness) -{ - // Precalculate vectors and dot products - float3 H = normalize (V + L); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - - // Light color fixed - float3 lightColor = float3(1.0, 1.0, 1.0); - - float3 color = float3(0.0, 0.0, 0.0); - - if (dotNL > 0.0) { - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, roughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - float3 F = F_Schlick(dotNV, F0); - float3 spec = D * F * G / (4.0 * dotNL * dotNV + 0.001); - float3 kD = (float3(1.0, 1.0, 1.0) - F) * (1.0 - metallic); - color += (kD * ALBEDO / PI + spec) * dotNL; - } - - return color; -} - -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 V = normalize(ubo.camPos - input.WorldPos); - float3 R = reflect(-V, N); - - float metallic = material.metallic; - float roughness = material.roughness; - - float3 F0 = float3(0.04, 0.04, 0.04); - F0 = lerp(F0, ALBEDO, metallic); - - float3 Lo = float3(0.0, 0.0, 0.0); - for(int i = 0; i < 4; i++) { - float3 L = normalize(uboParams.lights[i].xyz - input.WorldPos); - Lo += specularContribution(L, V, N, F0, metallic, roughness); - } - - float2 brdf = textureBRDFLUT.Sample(samplerBRDFLUT, float2(max(dot(N, V), 0.0), roughness)).rg; - float3 reflection = prefilteredReflection(R, roughness).rgb; - float3 irradiance = textureIrradiance.Sample(samplerIrradiance, N).rgb; - - // Diffuse based on irradiance - float3 diffuse = irradiance * ALBEDO; - - float3 F = F_SchlickR(max(dot(N, V), 0.0), F0, roughness); - - // Specular reflectance - float3 specular = reflection * (F * brdf.x + brdf.y); - - // Ambient part - float3 kD = 1.0 - F; - kD *= 1.0 - metallic; - float3 ambient = (kD * diffuse + specular); - - float3 color = ambient + Lo; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap((11.2f).xxx)); - // Gamma correction - color = pow(color, (1.0f / uboParams.gamma).xxx); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/pbribl/pbribl.frag.spv b/shaders/hlsl/pbribl/pbribl.frag.spv deleted file mode 100644 index 2cca9866..00000000 Binary files a/shaders/hlsl/pbribl/pbribl.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbribl/pbribl.vert b/shaders/hlsl/pbribl/pbribl.vert deleted file mode 100644 index 12d2e6e7..00000000 --- a/shaders/hlsl/pbribl/pbribl.vert +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 WorldPos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct PushConsts { - float3 objPos; -}; -[[vk::push_constant]] PushConsts pushConsts; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - float3 locPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.WorldPos = locPos + pushConsts.objPos; - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.UV = input.UV; - output.UV.y = 1.0 - input.UV.y; - output.Pos = mul(ubo.projection, mul(ubo.view, float4(output.WorldPos, 1.0))); - return output; -} diff --git a/shaders/hlsl/pbribl/pbribl.vert.spv b/shaders/hlsl/pbribl/pbribl.vert.spv deleted file mode 100644 index 67a8450e..00000000 Binary files a/shaders/hlsl/pbribl/pbribl.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pbribl/prefilterenvmap.frag b/shaders/hlsl/pbribl/prefilterenvmap.frag deleted file mode 100644 index 1f605d04..00000000 --- a/shaders/hlsl/pbribl/prefilterenvmap.frag +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureEnv : register(t0); -SamplerState samplerEnv : register(s0); - -struct PushConsts { -[[vk::offset(64)]] float roughness; -[[vk::offset(68)]] uint numSamples; -}; -[[vk::push_constant]] PushConsts consts; - -#define PI 3.1415926536 - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(float2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,float2(a,b)); - float sn= fmod(dt,3.14); - return frac(sin(sn) * c); -} - -float2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return float2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -float3 importanceSample_GGX(float2 Xi, float roughness, float3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - float3 up = abs(normal.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); - float3 tangentX = normalize(cross(up, normal)); - float3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Normal Distribution function -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -float3 prefilterEnvMap(float3 R, float roughness) -{ - float3 N = R; - float3 V = R; - float3 color = float3(0.0, 0.0, 0.0); - float totalWeight = 0.0; - int2 envMapDims; - textureEnv.GetDimensions(envMapDims.x, envMapDims.y); - float envMapDim = float(envMapDims.x); - for(uint i = 0u; i < consts.numSamples; i++) { - float2 Xi = hammersley2d(i, consts.numSamples); - float3 H = importanceSample_GGX(Xi, roughness, N); - float3 L = 2.0 * dot(V, H) * H - V; - float dotNL = clamp(dot(N, L), 0.0, 1.0); - if(dotNL > 0.0) { - // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ - - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotVH = clamp(dot(V, H), 0.0, 1.0); - - // Probability Distribution Function - float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; - // Slid angle of current smple - float omegaS = 1.0 / (float(consts.numSamples) * pdf); - // Solid angle of 1 pixel across all cube faces - float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); - // Biased (+1.0) mip level for better result - float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); - color += textureEnv.SampleLevel(samplerEnv, L, mipLevel).rgb * dotNL; - totalWeight += dotNL; - - } - } - return (color / totalWeight); -} - - -float4 main([[vk::location(0)]] float3 inPos : POSITION0) : SV_TARGET -{ - float3 N = normalize(inPos); - return float4(prefilterEnvMap(N, consts.roughness), 1.0); -} diff --git a/shaders/hlsl/pbribl/prefilterenvmap.frag.spv b/shaders/hlsl/pbribl/prefilterenvmap.frag.spv deleted file mode 100644 index 027bdf84..00000000 Binary files a/shaders/hlsl/pbribl/prefilterenvmap.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbribl/skybox.frag b/shaders/hlsl/pbribl/skybox.frag deleted file mode 100644 index 439c6287..00000000 --- a/shaders/hlsl/pbribl/skybox.frag +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureEnv : register(t2); -SamplerState samplerEnv : register(s2); - -struct UBOParams { - float4 lights[4]; - float exposure; - float gamma; -}; -cbuffer uboParams : register(b1) { UBOParams uboParams; }; - -// From http://filmicworlds.com/blog/filmic-tonemapping-operators/ -float3 Uncharted2Tonemap(float3 color) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - float W = 11.2; - return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; -} - -float4 main([[vk::location(0)]] float3 inUVW : POSITION0) : SV_TARGET -{ - float3 color = textureEnv.Sample(samplerEnv, inUVW).rgb; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap((11.2f).xxx)); - // Gamma correction - color = pow(color, (1.0f / uboParams.gamma).xxx); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/pbribl/skybox.frag.spv b/shaders/hlsl/pbribl/skybox.frag.spv deleted file mode 100644 index 9731fbbc..00000000 Binary files a/shaders/hlsl/pbribl/skybox.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbribl/skybox.vert b/shaders/hlsl/pbribl/skybox.vert deleted file mode 100644 index 26e3fb6d..00000000 --- a/shaders/hlsl/pbribl/skybox.vert +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UVW : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UVW = input.Pos; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} diff --git a/shaders/hlsl/pbribl/skybox.vert.spv b/shaders/hlsl/pbribl/skybox.vert.spv deleted file mode 100644 index 698235d9..00000000 Binary files a/shaders/hlsl/pbribl/skybox.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pbrtexture/filtercube.vert b/shaders/hlsl/pbrtexture/filtercube.vert deleted file mode 100644 index 514b4dd2..00000000 --- a/shaders/hlsl/pbrtexture/filtercube.vert +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -}; - -struct PushConsts { -[[vk::offset(0)]] float4x4 mvp; -}; -[[vk::push_constant]] PushConsts pushConsts; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UVW : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UVW = input.Pos; - output.Pos = mul(pushConsts.mvp, float4(input.Pos.xyz, 1.0)); - return output; -} diff --git a/shaders/hlsl/pbrtexture/filtercube.vert.spv b/shaders/hlsl/pbrtexture/filtercube.vert.spv deleted file mode 100644 index 9b32c2dd..00000000 Binary files a/shaders/hlsl/pbrtexture/filtercube.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pbrtexture/genbrdflut.frag b/shaders/hlsl/pbrtexture/genbrdflut.frag deleted file mode 100644 index 64f325f7..00000000 --- a/shaders/hlsl/pbrtexture/genbrdflut.frag +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2020 Google LLC - -[[vk::constant_id(0)]] const uint NUM_SAMPLES = 1024u; - -#define PI 3.1415926536 - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(float2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,float2(a,b)); - float sn= fmod(dt,3.14); - return frac(sin(sn) * c); -} - -float2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return float2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -float3 importanceSample_GGX(float2 Xi, float roughness, float3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - float3 up = abs(normal.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); - float3 tangentX = normalize(cross(up, normal)); - float3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Geometric Shadowing function -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float k = (roughness * roughness) / 2.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -float2 BRDF(float NoV, float roughness) -{ - // Normal always points along z-axis for the 2D lookup - const float3 N = float3(0.0, 0.0, 1.0); - float3 V = float3(sqrt(1.0 - NoV*NoV), 0.0, NoV); - - float2 LUT = float2(0.0, 0.0); - for(uint i = 0u; i < NUM_SAMPLES; i++) { - float2 Xi = hammersley2d(i, NUM_SAMPLES); - float3 H = importanceSample_GGX(Xi, roughness, N); - float3 L = 2.0 * dot(V, H) * H - V; - - float dotNL = max(dot(N, L), 0.0); - float dotNV = max(dot(N, V), 0.0); - float dotVH = max(dot(V, H), 0.0); - float dotNH = max(dot(H, N), 0.0); - - if (dotNL > 0.0) { - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - float G_Vis = (G * dotVH) / (dotNH * dotNV); - float Fc = pow(1.0 - dotVH, 5.0); - LUT += float2((1.0 - Fc) * G_Vis, Fc * G_Vis); - } - } - return LUT / float(NUM_SAMPLES); -} - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - return float4(BRDF(inUV.x, inUV.y), 0.0, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/pbrtexture/genbrdflut.frag.spv b/shaders/hlsl/pbrtexture/genbrdflut.frag.spv deleted file mode 100644 index 899a81a5..00000000 Binary files a/shaders/hlsl/pbrtexture/genbrdflut.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbrtexture/genbrdflut.vert b/shaders/hlsl/pbrtexture/genbrdflut.vert deleted file mode 100644 index 188b7298..00000000 --- a/shaders/hlsl/pbrtexture/genbrdflut.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/pbrtexture/genbrdflut.vert.spv b/shaders/hlsl/pbrtexture/genbrdflut.vert.spv deleted file mode 100644 index 46c4b31f..00000000 Binary files a/shaders/hlsl/pbrtexture/genbrdflut.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pbrtexture/irradiancecube.frag b/shaders/hlsl/pbrtexture/irradiancecube.frag deleted file mode 100644 index 66d63bf6..00000000 --- a/shaders/hlsl/pbrtexture/irradiancecube.frag +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureEnv : register(t0); -SamplerState samplerEnv : register(s0); - -struct PushConsts { -[[vk::offset(64)]] float deltaPhi; -[[vk::offset(68)]] float deltaTheta; -}; -[[vk::push_constant]]PushConsts consts; - -#define PI 3.1415926535897932384626433832795 - -float4 main([[vk::location(0)]] float3 inPos : TEXCOORD0) : SV_TARGET -{ - float3 N = normalize(inPos); - float3 up = float3(0.0, 1.0, 0.0); - float3 right = normalize(cross(up, N)); - up = cross(N, right); - - const float TWO_PI = PI * 2.0; - const float HALF_PI = PI * 0.5; - - float3 color = float3(0.0, 0.0, 0.0); - uint sampleCount = 0u; - for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) { - for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) { - float3 tempVec = cos(phi) * right + sin(phi) * up; - float3 sampleVector = cos(theta) * N + sin(theta) * tempVec; - color += textureEnv.Sample(samplerEnv, sampleVector).rgb * cos(theta) * sin(theta); - sampleCount++; - } - } - return float4(PI * color / float(sampleCount), 1.0); -} diff --git a/shaders/hlsl/pbrtexture/irradiancecube.frag.spv b/shaders/hlsl/pbrtexture/irradiancecube.frag.spv deleted file mode 100644 index b3def200..00000000 Binary files a/shaders/hlsl/pbrtexture/irradiancecube.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbrtexture/pbrtexture.frag b/shaders/hlsl/pbrtexture/pbrtexture.frag deleted file mode 100644 index 6f86e5b3..00000000 --- a/shaders/hlsl/pbrtexture/pbrtexture.frag +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 WorldPos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Tangent : TEXCOORD1; -}; - -struct UBO { - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct UBOParams { - float4 lights[4]; - float exposure; - float gamma; -}; -cbuffer uboParams : register(b1) { UBOParams uboParams; }; - -TextureCube textureIrradiance : register(t2); -SamplerState samplerIrradiance : register(s2); -Texture2D textureBRDFLUT : register(t3); -SamplerState samplerBRDFLUT : register(s3); -TextureCube prefilteredMapTexture : register(t4); -SamplerState prefilteredMapSampler : register(s4); - -Texture2D albedoMapTexture : register(t5); -SamplerState albedoMapSampler : register(s5); -Texture2D normalMapTexture : register(t6); -SamplerState normalMapSampler : register(s6); -Texture2D aoMapTexture : register(t7); -SamplerState aoMapSampler : register(s7); -Texture2D metallicMapTexture : register(t8); -SamplerState metallicMapSampler : register(s8); -Texture2D roughnessMapTexture : register(t9); -SamplerState roughnessMapSampler : register(s9); - -#define PI 3.1415926535897932384626433832795 -#define ALBEDO(uv) pow(albedoMapTexture.Sample(albedoMapSampler, uv).rgb, float3(2.2, 2.2, 2.2)) - -// From http://filmicgames.com/archives/75 -float3 Uncharted2Tonemap(float3 x) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F; -} - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -float3 F_Schlick(float cosTheta, float3 F0) -{ - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} -float3 F_SchlickR(float cosTheta, float3 F0, float roughness) -{ - return F0 + (max((1.0 - roughness).xxx, F0) - F0) * pow(1.0 - cosTheta, 5.0); -} - -float3 prefilteredReflection(float3 R, float roughness) -{ - const float MAX_REFLECTION_LOD = 9.0; // todo: param/const - float lod = roughness * MAX_REFLECTION_LOD; - float lodf = floor(lod); - float lodc = ceil(lod); - float3 a = prefilteredMapTexture.SampleLevel(prefilteredMapSampler, R, lodf).rgb; - float3 b = prefilteredMapTexture.SampleLevel(prefilteredMapSampler, R, lodc).rgb; - return lerp(a, b, lod - lodf); -} - -float3 specularContribution(float2 inUV, float3 L, float3 V, float3 N, float3 F0, float metallic, float roughness) -{ - // Precalculate vectors and dot products - float3 H = normalize (V + L); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - - // Light color fixed - float3 lightColor = float3(1.0, 1.0, 1.0); - - float3 color = float3(0.0, 0.0, 0.0); - - if (dotNL > 0.0) { - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, roughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - float3 F = F_Schlick(dotNV, F0); - float3 spec = D * F * G / (4.0 * dotNL * dotNV + 0.001); - float3 kD = (float3(1.0, 1.0, 1.0) - F) * (1.0 - metallic); - color += (kD * ALBEDO(inUV) / PI + spec) * dotNL; - } - - return color; -} - -float3 calculateNormal(VSOutput input) -{ - float3 tangentNormal = normalMapTexture.Sample(normalMapSampler, input.UV).xyz * 2.0 - 1.0; - - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent); - float3 B = normalize(cross(N, T)); - float3x3 TBN = transpose(float3x3(T, B, N)); - - return normalize(mul(TBN, tangentNormal)); -} - -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = calculateNormal(input); - float3 V = normalize(ubo.camPos - input.WorldPos); - float3 R = reflect(-V, N); - - float metallic = metallicMapTexture.Sample(metallicMapSampler, input.UV).r; - float roughness = roughnessMapTexture.Sample(roughnessMapSampler, input.UV).r; - - float3 F0 = float3(0.04, 0.04, 0.04); - F0 = lerp(F0, ALBEDO(input.UV), metallic); - - float3 Lo = float3(0.0, 0.0, 0.0); - for(int i = 0; i < 4; i++) { - float3 L = normalize(uboParams.lights[i].xyz - input.WorldPos); - Lo += specularContribution(input.UV, L, V, N, F0, metallic, roughness); - } - - float2 brdf = textureBRDFLUT.Sample(samplerBRDFLUT, float2(max(dot(N, V), 0.0), roughness)).rg; - float3 reflection = prefilteredReflection(R, roughness).rgb; - float3 irradiance = textureIrradiance.Sample(samplerIrradiance, N).rgb; - - // Diffuse based on irradiance - float3 diffuse = irradiance * ALBEDO(input.UV); - - float3 F = F_SchlickR(max(dot(N, V), 0.0), F0, roughness); - - // Specular reflectance - float3 specular = reflection * (F * brdf.x + brdf.y); - - // Ambient part - float3 kD = 1.0 - F; - kD *= 1.0 - metallic; - float3 ambient = (kD * diffuse + specular) * aoMapTexture.Sample(aoMapSampler, input.UV).rrr; - - float3 color = ambient + Lo; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap((11.2f).xxx)); - // Gamma correction - color = pow(color, (1.0f / uboParams.gamma).xxx); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/pbrtexture/pbrtexture.frag.spv b/shaders/hlsl/pbrtexture/pbrtexture.frag.spv deleted file mode 100644 index fea7d066..00000000 Binary files a/shaders/hlsl/pbrtexture/pbrtexture.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbrtexture/pbrtexture.vert b/shaders/hlsl/pbrtexture/pbrtexture.vert deleted file mode 100644 index 1a13886e..00000000 --- a/shaders/hlsl/pbrtexture/pbrtexture.vert +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float4 Tangent : TEXCOORD1; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 WorldPos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Tangent : TEXCOORD1; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - float3 locPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.WorldPos = locPos; - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.Tangent = mul((float3x3)ubo.model, input.Tangent); - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.view, float4(output.WorldPos, 1.0))); - return output; -} diff --git a/shaders/hlsl/pbrtexture/pbrtexture.vert.spv b/shaders/hlsl/pbrtexture/pbrtexture.vert.spv deleted file mode 100644 index 44e2c7f9..00000000 Binary files a/shaders/hlsl/pbrtexture/pbrtexture.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pbrtexture/prefilterenvmap.frag b/shaders/hlsl/pbrtexture/prefilterenvmap.frag deleted file mode 100644 index 1f605d04..00000000 --- a/shaders/hlsl/pbrtexture/prefilterenvmap.frag +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureEnv : register(t0); -SamplerState samplerEnv : register(s0); - -struct PushConsts { -[[vk::offset(64)]] float roughness; -[[vk::offset(68)]] uint numSamples; -}; -[[vk::push_constant]] PushConsts consts; - -#define PI 3.1415926536 - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(float2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,float2(a,b)); - float sn= fmod(dt,3.14); - return frac(sin(sn) * c); -} - -float2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return float2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -float3 importanceSample_GGX(float2 Xi, float roughness, float3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - float3 up = abs(normal.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); - float3 tangentX = normalize(cross(up, normal)); - float3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Normal Distribution function -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -float3 prefilterEnvMap(float3 R, float roughness) -{ - float3 N = R; - float3 V = R; - float3 color = float3(0.0, 0.0, 0.0); - float totalWeight = 0.0; - int2 envMapDims; - textureEnv.GetDimensions(envMapDims.x, envMapDims.y); - float envMapDim = float(envMapDims.x); - for(uint i = 0u; i < consts.numSamples; i++) { - float2 Xi = hammersley2d(i, consts.numSamples); - float3 H = importanceSample_GGX(Xi, roughness, N); - float3 L = 2.0 * dot(V, H) * H - V; - float dotNL = clamp(dot(N, L), 0.0, 1.0); - if(dotNL > 0.0) { - // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ - - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotVH = clamp(dot(V, H), 0.0, 1.0); - - // Probability Distribution Function - float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; - // Slid angle of current smple - float omegaS = 1.0 / (float(consts.numSamples) * pdf); - // Solid angle of 1 pixel across all cube faces - float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); - // Biased (+1.0) mip level for better result - float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); - color += textureEnv.SampleLevel(samplerEnv, L, mipLevel).rgb * dotNL; - totalWeight += dotNL; - - } - } - return (color / totalWeight); -} - - -float4 main([[vk::location(0)]] float3 inPos : POSITION0) : SV_TARGET -{ - float3 N = normalize(inPos); - return float4(prefilterEnvMap(N, consts.roughness), 1.0); -} diff --git a/shaders/hlsl/pbrtexture/prefilterenvmap.frag.spv b/shaders/hlsl/pbrtexture/prefilterenvmap.frag.spv deleted file mode 100644 index 027bdf84..00000000 Binary files a/shaders/hlsl/pbrtexture/prefilterenvmap.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbrtexture/skybox.frag b/shaders/hlsl/pbrtexture/skybox.frag deleted file mode 100644 index 439c6287..00000000 --- a/shaders/hlsl/pbrtexture/skybox.frag +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureEnv : register(t2); -SamplerState samplerEnv : register(s2); - -struct UBOParams { - float4 lights[4]; - float exposure; - float gamma; -}; -cbuffer uboParams : register(b1) { UBOParams uboParams; }; - -// From http://filmicworlds.com/blog/filmic-tonemapping-operators/ -float3 Uncharted2Tonemap(float3 color) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - float W = 11.2; - return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; -} - -float4 main([[vk::location(0)]] float3 inUVW : POSITION0) : SV_TARGET -{ - float3 color = textureEnv.Sample(samplerEnv, inUVW).rgb; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap((11.2f).xxx)); - // Gamma correction - color = pow(color, (1.0f / uboParams.gamma).xxx); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/pbrtexture/skybox.frag.spv b/shaders/hlsl/pbrtexture/skybox.frag.spv deleted file mode 100644 index 9731fbbc..00000000 Binary files a/shaders/hlsl/pbrtexture/skybox.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pbrtexture/skybox.vert b/shaders/hlsl/pbrtexture/skybox.vert deleted file mode 100644 index 26e3fb6d..00000000 --- a/shaders/hlsl/pbrtexture/skybox.vert +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UVW : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UVW = input.Pos; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} diff --git a/shaders/hlsl/pbrtexture/skybox.vert.spv b/shaders/hlsl/pbrtexture/skybox.vert.spv deleted file mode 100644 index 698235d9..00000000 Binary files a/shaders/hlsl/pbrtexture/skybox.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pipelines/phong.frag b/shaders/hlsl/pipelines/phong.frag deleted file mode 100644 index f9c98a57..00000000 --- a/shaders/hlsl/pipelines/phong.frag +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - // Desaturate color - float3 color = lerp(input.Color, dot(float3(0.2126,0.7152,0.0722), input.Color).xxx, 0.65); - - // High ambient colors because mesh materials are pretty dark - float3 ambient = color * float3(1.0, 1.0, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color; - float3 specular = pow(max(dot(R, V), 0.0), 32.0) * float3(0.35, 0.35, 0.35); - return float4(ambient + diffuse * 1.75 + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/pipelines/phong.frag.spv b/shaders/hlsl/pipelines/phong.frag.spv deleted file mode 100644 index fc9604e6..00000000 Binary files a/shaders/hlsl/pipelines/phong.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pipelines/phong.vert b/shaders/hlsl/pipelines/phong.vert deleted file mode 100644 index de0aa110..00000000 --- a/shaders/hlsl/pipelines/phong.vert +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/pipelines/phong.vert.spv b/shaders/hlsl/pipelines/phong.vert.spv deleted file mode 100644 index 6d9f4243..00000000 Binary files a/shaders/hlsl/pipelines/phong.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pipelines/toon.frag b/shaders/hlsl/pipelines/toon.frag deleted file mode 100644 index 7f91459e..00000000 --- a/shaders/hlsl/pipelines/toon.frag +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - // Desaturate color - float3 color = lerp(input.Color, dot(float3(0.2126,0.7152,0.0722), input.Color).xxx, 0.65); - - // High ambient colors because mesh materials are pretty dark - float3 ambient = color * float3(1.0, 1.0, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - - float intensity = dot(N,L); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - return float4(input.Color * 3.0 * shade, 1); -} \ No newline at end of file diff --git a/shaders/hlsl/pipelines/toon.frag.spv b/shaders/hlsl/pipelines/toon.frag.spv deleted file mode 100644 index 92714cc1..00000000 Binary files a/shaders/hlsl/pipelines/toon.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pipelines/toon.vert b/shaders/hlsl/pipelines/toon.vert deleted file mode 100644 index de0aa110..00000000 --- a/shaders/hlsl/pipelines/toon.vert +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/pipelines/toon.vert.spv b/shaders/hlsl/pipelines/toon.vert.spv deleted file mode 100644 index 6d9f4243..00000000 Binary files a/shaders/hlsl/pipelines/toon.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pipelines/wireframe.frag b/shaders/hlsl/pipelines/wireframe.frag deleted file mode 100644 index 0ff24dd0..00000000 --- a/shaders/hlsl/pipelines/wireframe.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main([[vk::location(0)]] float3 Color : COLOR0) : SV_TARGET -{ - return float4(Color * 1.5, 1); -} \ No newline at end of file diff --git a/shaders/hlsl/pipelines/wireframe.frag.spv b/shaders/hlsl/pipelines/wireframe.frag.spv deleted file mode 100644 index 7b7a8460..00000000 Binary files a/shaders/hlsl/pipelines/wireframe.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pipelines/wireframe.vert b/shaders/hlsl/pipelines/wireframe.vert deleted file mode 100644 index 7f89ba04..00000000 --- a/shaders/hlsl/pipelines/wireframe.vert +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, input.Pos)); - return output; -} diff --git a/shaders/hlsl/pipelines/wireframe.vert.spv b/shaders/hlsl/pipelines/wireframe.vert.spv deleted file mode 100644 index 00e07dc8..00000000 Binary files a/shaders/hlsl/pipelines/wireframe.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pipelinestatistics/scene.frag b/shaders/hlsl/pipelinestatistics/scene.frag deleted file mode 100644 index 4cd20bf5..00000000 --- a/shaders/hlsl/pipelinestatistics/scene.frag +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse + specular, 0.5); -} \ No newline at end of file diff --git a/shaders/hlsl/pipelinestatistics/scene.frag.spv b/shaders/hlsl/pipelinestatistics/scene.frag.spv deleted file mode 100644 index 2e7c9af5..00000000 Binary files a/shaders/hlsl/pipelinestatistics/scene.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pipelinestatistics/scene.tesc b/shaders/hlsl/pipelinestatistics/scene.tesc deleted file mode 100644 index bed96a0e..00000000 --- a/shaders/hlsl/pipelinestatistics/scene.tesc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -struct HSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner : SV_InsideTessFactor; -}; - -ConstantsHSOutput ConstantsHS(InputPatch patch, uint InvocationID : SV_PrimitiveID) -{ - ConstantsHSOutput output = (ConstantsHSOutput)0; - output.TessLevelInner = 2.0; - output.TessLevelOuter[0] = 1.0; - output.TessLevelOuter[1] = 1.0; - output.TessLevelOuter[2] = 1.0; - return output; -} - -[domain("tri")] -[partitioning("integer")] -[outputtopology("triangle_ccw")] -[outputcontrolpoints(3)] -[patchconstantfunc("ConstantsHS")] -[maxtessfactor(20.0f)] -HSOutput main(InputPatch patch, uint InvocationID : SV_OutputControlPointID) -{ - HSOutput output = (HSOutput)0; - output.Pos = patch[InvocationID].Pos; - output.Normal = patch[InvocationID].Normal; - output.Color = patch[InvocationID].Color; - output.ViewVec = patch[InvocationID].ViewVec; - output.LightVec = patch[InvocationID].LightVec; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/pipelinestatistics/scene.tesc.spv b/shaders/hlsl/pipelinestatistics/scene.tesc.spv deleted file mode 100644 index 41cc5673..00000000 Binary files a/shaders/hlsl/pipelinestatistics/scene.tesc.spv and /dev/null differ diff --git a/shaders/hlsl/pipelinestatistics/scene.tese b/shaders/hlsl/pipelinestatistics/scene.tese deleted file mode 100644 index 1cccb2b2..00000000 --- a/shaders/hlsl/pipelinestatistics/scene.tese +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 Google LLC - -struct HSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner : SV_InsideTessFactor; -}; - -struct DSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -[domain("tri")] -DSOutput main(ConstantsHSOutput input, float3 TessCoord : SV_DomainLocation, const OutputPatch patch) -{ - DSOutput output = (DSOutput)0; - output.Pos = (TessCoord.x * patch[2].Pos) + - (TessCoord.y * patch[1].Pos) + - (TessCoord.z * patch[0].Pos); - output.Normal = TessCoord.x * patch[2].Normal + TessCoord.y * patch[1].Normal + TessCoord.z * patch[0].Normal; - output.ViewVec = TessCoord.x * patch[2].ViewVec + TessCoord.y * patch[1].ViewVec + TessCoord.z * patch[0].ViewVec; - output.LightVec = TessCoord.x * patch[2].LightVec + TessCoord.y * patch[1].LightVec + TessCoord.z * patch[0].LightVec; - output.Color = patch[0].Color; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/pipelinestatistics/scene.tese.spv b/shaders/hlsl/pipelinestatistics/scene.tese.spv deleted file mode 100644 index 665ad2d9..00000000 Binary files a/shaders/hlsl/pipelinestatistics/scene.tese.spv and /dev/null differ diff --git a/shaders/hlsl/pipelinestatistics/scene.vert b/shaders/hlsl/pipelinestatistics/scene.vert deleted file mode 100644 index a11fe37c..00000000 --- a/shaders/hlsl/pipelinestatistics/scene.vert +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -struct PushConsts { - float3 objPos; -}; -[[vk::push_constant]] PushConsts pushConsts; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - - float3 locPos = mul(ubo.modelview, float4(input.Pos, 1.0)).xyz; - float3 worldPos = mul(ubo.modelview, float4(input.Pos + pushConsts.objPos, 1.0)).xyz; - output.Pos = mul(ubo.projection, float4(worldPos, 1.0)); - - float4 pos = mul(ubo.modelview, float4(worldPos, 1.0)); - output.Normal = mul((float3x3)ubo.modelview, input.Normal); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/pipelinestatistics/scene.vert.spv b/shaders/hlsl/pipelinestatistics/scene.vert.spv deleted file mode 100644 index f9af87c1..00000000 Binary files a/shaders/hlsl/pipelinestatistics/scene.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pushconstants/pushconstants.frag b/shaders/hlsl/pushconstants/pushconstants.frag deleted file mode 100644 index 505af88a..00000000 --- a/shaders/hlsl/pushconstants/pushconstants.frag +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Color : COLOR0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - return float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/pushconstants/pushconstants.frag.spv b/shaders/hlsl/pushconstants/pushconstants.frag.spv deleted file mode 100644 index 572c1e3e..00000000 Binary files a/shaders/hlsl/pushconstants/pushconstants.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pushconstants/pushconstants.vert b/shaders/hlsl/pushconstants/pushconstants.vert deleted file mode 100644 index c6c7f8e7..00000000 --- a/shaders/hlsl/pushconstants/pushconstants.vert +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct PushConsts { - float4 color; - float4 position; -}; -[[vk::push_constant]] PushConsts pushConsts; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color * pushConsts.color.rgb; - - float3 locPos = float3(mul(ubo.model, float4(input.Pos.xyz, 1.0)).xyz); - float3 worldPos = locPos + pushConsts.position.xyz; - output.Pos = mul(ubo.projection, mul(ubo.view, float4(worldPos.xyz, 1.0))); - - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/pushconstants/pushconstants.vert.spv b/shaders/hlsl/pushconstants/pushconstants.vert.spv deleted file mode 100644 index 8ed9d921..00000000 Binary files a/shaders/hlsl/pushconstants/pushconstants.vert.spv and /dev/null differ diff --git a/shaders/hlsl/pushdescriptors/cube.frag b/shaders/hlsl/pushdescriptors/cube.frag deleted file mode 100644 index 69ede0b8..00000000 --- a/shaders/hlsl/pushdescriptors/cube.frag +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t2); -SamplerState samplerColorMap : register(s2); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - return textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/pushdescriptors/cube.frag.spv b/shaders/hlsl/pushdescriptors/cube.frag.spv deleted file mode 100644 index 1bf94243..00000000 Binary files a/shaders/hlsl/pushdescriptors/cube.frag.spv and /dev/null differ diff --git a/shaders/hlsl/pushdescriptors/cube.vert b/shaders/hlsl/pushdescriptors/cube.vert deleted file mode 100644 index 9a8366a0..00000000 --- a/shaders/hlsl/pushdescriptors/cube.vert +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBOScene { - float4x4 projection; - float4x4 view; -}; -cbuffer uboCamera : register(b0) { UBOScene uboCamera; }; - -struct UBOModel { - float4x4 local; -}; -cbuffer uboModel : register(b1) { UBOModel uboModel; }; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(uboCamera.projection, mul(uboCamera.view, mul(uboModel.local, float4(input.Pos.xyz, 1.0)))); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/pushdescriptors/cube.vert.spv b/shaders/hlsl/pushdescriptors/cube.vert.spv deleted file mode 100644 index d5f4a64e..00000000 Binary files a/shaders/hlsl/pushdescriptors/cube.vert.spv and /dev/null differ diff --git a/shaders/hlsl/radialblur/colorpass.frag b/shaders/hlsl/radialblur/colorpass.frag deleted file mode 100644 index 08577814..00000000 --- a/shaders/hlsl/radialblur/colorpass.frag +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureGradientRamp : register(t1); -SamplerState samplerGradientRamp : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Color : COLOR0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - // Use max. color channel value to detect bright glow emitters - if ((input.Color.r >= 0.9) || (input.Color.g >= 0.9) || (input.Color.b >= 0.9)) - { - return float4(textureGradientRamp.Sample(samplerGradientRamp, input.UV).rgb, 1); - } - else - { - return float4(input.Color, 1); - } -} \ No newline at end of file diff --git a/shaders/hlsl/radialblur/colorpass.frag.spv b/shaders/hlsl/radialblur/colorpass.frag.spv deleted file mode 100644 index 7dc782fa..00000000 Binary files a/shaders/hlsl/radialblur/colorpass.frag.spv and /dev/null differ diff --git a/shaders/hlsl/radialblur/colorpass.vert b/shaders/hlsl/radialblur/colorpass.vert deleted file mode 100644 index a82eedea..00000000 --- a/shaders/hlsl/radialblur/colorpass.vert +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float gradientPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.UV = float2(ubo.gradientPos, 0.0f); - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos, 1.0))); - return output; -} diff --git a/shaders/hlsl/radialblur/colorpass.vert.spv b/shaders/hlsl/radialblur/colorpass.vert.spv deleted file mode 100644 index 5d849c47..00000000 Binary files a/shaders/hlsl/radialblur/colorpass.vert.spv and /dev/null differ diff --git a/shaders/hlsl/radialblur/phongpass.frag b/shaders/hlsl/radialblur/phongpass.frag deleted file mode 100644 index 1360ff30..00000000 --- a/shaders/hlsl/radialblur/phongpass.frag +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureGradientRamp : register(t1); -SamplerState samplerGradientRamp : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 EyePos : POSITION0; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -[[vk::location(4)]] float2 UV : TEXCOORD0; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - // No light calculations for glow color - // Use max. color channel value - // to detect bright glow emitters - if ((input.Color.r >= 0.9) || (input.Color.g >= 0.9) || (input.Color.b >= 0.9)) - { - return float4(textureGradientRamp.Sample(samplerGradientRamp, input.UV).rgb, 1); - } - else - { - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - - float4 IAmbient = float4(0.2, 0.2, 0.2, 1.0); - float4 IDiffuse = float4(0.5, 0.5, 0.5, 0.5) * max(dot(input.Normal, input.LightVec), 0.0); - float specular = 0.25; - float4 ISpecular = float4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 4.0) * specular; - return float4((IAmbient + IDiffuse) * float4(input.Color, 1.0) + ISpecular); - } -} \ No newline at end of file diff --git a/shaders/hlsl/radialblur/phongpass.frag.spv b/shaders/hlsl/radialblur/phongpass.frag.spv deleted file mode 100644 index f5f3b3f6..00000000 Binary files a/shaders/hlsl/radialblur/phongpass.frag.spv and /dev/null differ diff --git a/shaders/hlsl/radialblur/phongpass.vert b/shaders/hlsl/radialblur/phongpass.vert deleted file mode 100644 index 22b8974b..00000000 --- a/shaders/hlsl/radialblur/phongpass.vert +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float gradientPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 EyePos : POSITION0; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -[[vk::location(4)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = float2(ubo.gradientPos, 0.0); - output.Pos = mul(ubo.projection, mul(ubo.model, input.Pos)); - output.EyePos = mul(ubo.model, input.Pos).xyz; - float4 lightPos = float4(0.0, 0.0, -5.0, 1.0);// * ubo.model; - output.LightVec = normalize(lightPos.xyz - input.Pos.xyz); - return output; -} diff --git a/shaders/hlsl/radialblur/phongpass.vert.spv b/shaders/hlsl/radialblur/phongpass.vert.spv deleted file mode 100644 index a9d4eb24..00000000 Binary files a/shaders/hlsl/radialblur/phongpass.vert.spv and /dev/null differ diff --git a/shaders/hlsl/radialblur/radialblur.frag b/shaders/hlsl/radialblur/radialblur.frag deleted file mode 100644 index 3e41875e..00000000 --- a/shaders/hlsl/radialblur/radialblur.frag +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -struct UBO -{ - float radialBlurScale; - float radialBlurStrength; - float2 radialOrigin; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - int2 texDim; - textureColor.GetDimensions(texDim.x, texDim.y); - float2 radialSize = float2(1.0 / texDim.x, 1.0 / texDim.y); - - float2 UV = inUV; - - float4 color = float4(0.0, 0.0, 0.0, 0.0); - UV += radialSize * 0.5 - ubo.radialOrigin; - - #define samples 32 - - for (int i = 0; i < samples; i++) - { - float scale = 1.0 - ubo.radialBlurScale * (float(i) / float(samples-1)); - color += textureColor.Sample(samplerColor, UV * scale + ubo.radialOrigin); - } - - return (color / samples) * ubo.radialBlurStrength; -} \ No newline at end of file diff --git a/shaders/hlsl/radialblur/radialblur.frag.spv b/shaders/hlsl/radialblur/radialblur.frag.spv deleted file mode 100644 index 34db5e2b..00000000 Binary files a/shaders/hlsl/radialblur/radialblur.frag.spv and /dev/null differ diff --git a/shaders/hlsl/radialblur/radialblur.vert b/shaders/hlsl/radialblur/radialblur.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/radialblur/radialblur.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/radialblur/radialblur.vert.spv b/shaders/hlsl/radialblur/radialblur.vert.spv deleted file mode 100644 index 46c4b31f..00000000 Binary files a/shaders/hlsl/radialblur/radialblur.vert.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingbasic/closesthit.rchit b/shaders/hlsl/raytracingbasic/closesthit.rchit deleted file mode 100644 index 98655f73..00000000 --- a/shaders/hlsl/raytracingbasic/closesthit.rchit +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Google LLC - -struct Attributes -{ - float2 bary; -}; - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -[shader("closesthit")] -void main(inout Payload p, in Attributes attribs) -{ - const float3 barycentricCoords = float3(1.0f - attribs.bary.x - attribs.bary.y, attribs.bary.x, attribs.bary.y); - p.hitValue = barycentricCoords; -} diff --git a/shaders/hlsl/raytracingbasic/closesthit.rchit.spv b/shaders/hlsl/raytracingbasic/closesthit.rchit.spv deleted file mode 100644 index 58768f06..00000000 Binary files a/shaders/hlsl/raytracingbasic/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingbasic/miss.rmiss b/shaders/hlsl/raytracingbasic/miss.rmiss deleted file mode 100644 index d9e274c0..00000000 --- a/shaders/hlsl/raytracingbasic/miss.rmiss +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2020 Google LLC - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -[shader("miss")] -void main(inout Payload p) -{ - p.hitValue = float3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingbasic/miss.rmiss.spv b/shaders/hlsl/raytracingbasic/miss.rmiss.spv deleted file mode 100644 index 5eacf24a..00000000 Binary files a/shaders/hlsl/raytracingbasic/miss.rmiss.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingbasic/raygen.rgen b/shaders/hlsl/raytracingbasic/raygen.rgen deleted file mode 100644 index d30bb92e..00000000 --- a/shaders/hlsl/raytracingbasic/raygen.rgen +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 Google LLC - -RaytracingAccelerationStructure rs : register(t0); -RWTexture2D image : register(u1); - -struct CameraProperties -{ - float4x4 viewInverse; - float4x4 projInverse; -}; -cbuffer cam : register(b2) { CameraProperties cam; }; - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -[shader("raygeneration")] -void main() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter/float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0,0,0,1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - TraceRay(rs, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} diff --git a/shaders/hlsl/raytracingbasic/raygen.rgen.spv b/shaders/hlsl/raytracingbasic/raygen.rgen.spv deleted file mode 100644 index f0a0a140..00000000 Binary files a/shaders/hlsl/raytracingbasic/raygen.rgen.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingcallable/callable1.rcall b/shaders/hlsl/raytracingcallable/callable1.rcall deleted file mode 100644 index 5a40044d..00000000 --- a/shaders/hlsl/raytracingcallable/callable1.rcall +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2021 Sascha Willems - -struct CallData -{ - float3 outColor; -}; - -[shader("callable")] -void main(inout CallData data) -{ - // Generate a checker board pattern - float2 pos = float2(DispatchRaysIndex().x / 8, DispatchRaysIndex().y / 8); - float col = (pos.x + (pos.y % 2.0)) % 2.0; - data.outColor = float3(col, col, col); -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingcallable/callable1.rcall.spv b/shaders/hlsl/raytracingcallable/callable1.rcall.spv deleted file mode 100644 index 79fe2d19..00000000 Binary files a/shaders/hlsl/raytracingcallable/callable1.rcall.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingcallable/callable2.rcall b/shaders/hlsl/raytracingcallable/callable2.rcall deleted file mode 100644 index 86789325..00000000 --- a/shaders/hlsl/raytracingcallable/callable2.rcall +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2021 Sascha Willems - -struct CallData -{ - float3 outColor; -}; - -[shader("callable")] -void main(inout CallData data) -{ - data.outColor = float3(0.0, 1.0, 0.0); -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingcallable/callable2.rcall.spv b/shaders/hlsl/raytracingcallable/callable2.rcall.spv deleted file mode 100644 index fb4c4f39..00000000 Binary files a/shaders/hlsl/raytracingcallable/callable2.rcall.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingcallable/callable3.rcall b/shaders/hlsl/raytracingcallable/callable3.rcall deleted file mode 100644 index 3fe4fd85..00000000 --- a/shaders/hlsl/raytracingcallable/callable3.rcall +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2021 Sascha Willems - -struct CallData -{ - float3 outColor; -}; - -[shader("callable")] -void main(inout CallData data) -{ - // Generate a checker board pattern - float2 pos = float2(DispatchRaysIndex().x / 8, DispatchRaysIndex().y / 8); - float col = pos.y % 2.0; - data.outColor = float3(col, col, col); -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingcallable/callable3.rcall.spv b/shaders/hlsl/raytracingcallable/callable3.rcall.spv deleted file mode 100644 index 41794274..00000000 Binary files a/shaders/hlsl/raytracingcallable/callable3.rcall.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingcallable/closesthit.rchit b/shaders/hlsl/raytracingcallable/closesthit.rchit deleted file mode 100644 index eba5791c..00000000 --- a/shaders/hlsl/raytracingcallable/closesthit.rchit +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2021-2023 Sascha Willems - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -struct CallData -{ - float3 outColor; -}; - -struct Attributes -{ - float2 bary; -}; - -[shader("closesthit")] -void main(inout Payload p, in Attributes attribs) -{ - // Execute the callable shader indexed by the current geometry being hit - // For our sample this means that the first callable shader in the SBT is invoked for the first triangle, the second callable shader for the second triangle, etc. - CallData callData; - CallShader(GeometryIndex(), callData); - p.hitValue = callData.outColor; -} diff --git a/shaders/hlsl/raytracingcallable/closesthit.rchit.spv b/shaders/hlsl/raytracingcallable/closesthit.rchit.spv deleted file mode 100644 index 1b2f22f9..00000000 Binary files a/shaders/hlsl/raytracingcallable/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingcallable/miss.rmiss b/shaders/hlsl/raytracingcallable/miss.rmiss deleted file mode 100644 index 3342b168..00000000 --- a/shaders/hlsl/raytracingcallable/miss.rmiss +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2021 Sascha Willems - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -[shader("miss")] -void main(inout Payload p) -{ - p.hitValue = float3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingcallable/miss.rmiss.spv b/shaders/hlsl/raytracingcallable/miss.rmiss.spv deleted file mode 100644 index 839732c5..00000000 Binary files a/shaders/hlsl/raytracingcallable/miss.rmiss.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingcallable/raygen.rgen b/shaders/hlsl/raytracingcallable/raygen.rgen deleted file mode 100644 index 6e08cd05..00000000 --- a/shaders/hlsl/raytracingcallable/raygen.rgen +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2021 Sascha Willems - -RaytracingAccelerationStructure rs : register(t0); -RWTexture2D image : register(u1); - -struct CameraProperties -{ - float4x4 viewInverse; - float4x4 projInverse; -}; -cbuffer cam : register(b2) { CameraProperties cam; }; - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -[shader("raygeneration")] -void main() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter/float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0,0,0,1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - TraceRay(rs, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} diff --git a/shaders/hlsl/raytracingcallable/raygen.rgen.spv b/shaders/hlsl/raytracingcallable/raygen.rgen.spv deleted file mode 100644 index 611d1de1..00000000 Binary files a/shaders/hlsl/raytracingcallable/raygen.rgen.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingpositionfetch/closesthit.rchit b/shaders/hlsl/raytracingpositionfetch/closesthit.rchit deleted file mode 100644 index 2223640c..00000000 --- a/shaders/hlsl/raytracingpositionfetch/closesthit.rchit +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2024, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Attributes -{ - float2 bary; -}; - -struct Payload -{ - [[vk::location(0)]] float3 hitValue; -}; - -struct UBO -{ - float4x4 viewInverse; - float4x4 projInverse; - float4 lightPos; -}; -ConstantBuffer ubo : register(b2); - -// We need to use special syntax for SPIR-V inlines -#define HitTriangleVertexPositionsKHR 5335 -#define RayTracingPositionFetchKHR 5336 - -[[vk::ext_extension("SPV_KHR_ray_tracing_position_fetch")]] -[[vk::ext_capability(RayTracingPositionFetchKHR)]] -[[vk::ext_builtin_input(HitTriangleVertexPositionsKHR)]] -const static float3 gl_HitTriangleVertexPositions[3]; - -[shader("closesthit")] -void main(inout Payload p, in Attributes attribs) -{ - // We need the barycentric coordinates to calculate data for the current position - const float3 barycentricCoords = float3(1.0f - attribs.bary.x - attribs.bary.y, attribs.bary.x, attribs.bary.y); - - // With VK_KHR_ray_tracing_position_fetch we can access the vertices for the hit triangle in the shader - - float3 vertexPos0 = gl_HitTriangleVertexPositions[0]; - float3 vertexPos1 = gl_HitTriangleVertexPositions[1]; - float3 vertexPos2 = gl_HitTriangleVertexPositions[2]; - float3 currentPos = vertexPos0 * barycentricCoords.x + vertexPos1 * barycentricCoords.y + vertexPos2 * barycentricCoords.z; - - // Calcualte the normal from above values - float3 normal = normalize(cross(vertexPos1 - vertexPos0, vertexPos2 - vertexPos0)); - normal = normalize(mul(float4(normal, 1.0), WorldToObject4x3())); - - // Basic lighting - float3 lightDir = normalize(ubo.lightPos.xyz - currentPos); - float diffuse = max(dot(normal, lightDir), 0.0); - - p.hitValue.rgb = 0.1 + diffuse; -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingpositionfetch/closesthit.rchit.spv b/shaders/hlsl/raytracingpositionfetch/closesthit.rchit.spv deleted file mode 100644 index cce003a5..00000000 Binary files a/shaders/hlsl/raytracingpositionfetch/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingpositionfetch/miss.rmiss b/shaders/hlsl/raytracingpositionfetch/miss.rmiss deleted file mode 100644 index e28ec877..00000000 --- a/shaders/hlsl/raytracingpositionfetch/miss.rmiss +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright (c) 2024, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -[shader("miss")] -void main(inout Payload p) -{ - p.hitValue = float3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingpositionfetch/miss.rmiss.spv b/shaders/hlsl/raytracingpositionfetch/miss.rmiss.spv deleted file mode 100644 index 9cc0453a..00000000 Binary files a/shaders/hlsl/raytracingpositionfetch/miss.rmiss.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingpositionfetch/raygen.rgen b/shaders/hlsl/raytracingpositionfetch/raygen.rgen deleted file mode 100644 index a346a62f..00000000 --- a/shaders/hlsl/raytracingpositionfetch/raygen.rgen +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) 2024, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -RaytracingAccelerationStructure rs : register(t0); -RWTexture2D image : register(u1); - -struct CameraProperties -{ - float4x4 viewInverse; - float4x4 projInverse; -}; -cbuffer cam : register(b2) { CameraProperties cam; }; - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -[shader("raygeneration")] -void main() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter/float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0,0,0,1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - TraceRay(rs, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} diff --git a/shaders/hlsl/raytracingpositionfetch/raygen.rgen.spv b/shaders/hlsl/raytracingpositionfetch/raygen.rgen.spv deleted file mode 100644 index 5535f2ed..00000000 Binary files a/shaders/hlsl/raytracingpositionfetch/raygen.rgen.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingreflections/closesthit.rchit b/shaders/hlsl/raytracingreflections/closesthit.rchit deleted file mode 100644 index 7159ecfd..00000000 --- a/shaders/hlsl/raytracingreflections/closesthit.rchit +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2020 Google LLC - -struct RayPayload -{ - float3 color; - float distance; - float3 normal; - float reflector; -}; - -struct Attributes -{ - float2 bary; -}; - -RaytracingAccelerationStructure topLevelAS : register(t0); -struct UBO -{ - float4x4 viewInverse; - float4x4 projInverse; - float4 lightPos; - int vertexSize; -}; -cbuffer ubo : register(b2) { UBO ubo; }; - -StructuredBuffer vertices : register(t3); -StructuredBuffer indices : register(t4); - -struct Vertex -{ - float3 pos; - float3 normal; - float2 uv; - float4 color; - float4 _pad0; - float4 _pad1; -}; - -Vertex unpack(uint index) -{ - // Unpack the vertices from the SSBO using the glTF vertex structure - // The multiplier is the size of the vertex divided by four float components (=16 bytes) - const int m = ubo.vertexSize / 16; - - float4 d0 = vertices[m * index + 0]; - float4 d1 = vertices[m * index + 1]; - float4 d2 = vertices[m * index + 2]; - - Vertex v; - v.pos = d0.xyz; - v.normal = float3(d0.w, d1.x, d1.y); - v.color = float4(d2.x, d2.y, d2.z, 1.0); - - return v; -} - -[shader("closesthit")] -void main(inout RayPayload rayPayload, in Attributes attribs) -{ - uint PrimitiveID = PrimitiveIndex(); - int3 index = int3(indices[3 * PrimitiveID], indices[3 * PrimitiveID + 1], indices[3 * PrimitiveID + 2]); - - Vertex v0 = unpack(index.x); - Vertex v1 = unpack(index.y); - Vertex v2 = unpack(index.z); - - // Interpolate normal - const float3 barycentricCoords = float3(1.0f - attribs.bary.x - attribs.bary.y, attribs.bary.x, attribs.bary.y); - float3 normal = normalize(v0.normal * barycentricCoords.x + v1.normal * barycentricCoords.y + v2.normal * barycentricCoords.z); - - // Basic lighting - float3 lightVector = normalize(ubo.lightPos.xyz); - float dot_product = max(dot(lightVector, normal), 0.6); - rayPayload.color.rgb = v0.color * dot_product; - rayPayload.distance = RayTCurrent(); - rayPayload.normal = normal; - - // Objects with full white vertex color are treated as reflectors - rayPayload.reflector = ((v0.color.r == 1.0f) && (v0.color.g == 1.0f) && (v0.color.b == 1.0f)) ? 1.0f : 0.0f; -} diff --git a/shaders/hlsl/raytracingreflections/closesthit.rchit.spv b/shaders/hlsl/raytracingreflections/closesthit.rchit.spv deleted file mode 100644 index 7616ea06..00000000 Binary files a/shaders/hlsl/raytracingreflections/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingreflections/miss.rmiss b/shaders/hlsl/raytracingreflections/miss.rmiss deleted file mode 100644 index 8f75824a..00000000 --- a/shaders/hlsl/raytracingreflections/miss.rmiss +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 Google LLC - -struct RayPayload { - float3 color; - float distance; - float3 normal; - float reflector; -}; - -[shader("miss")] -void main(inout RayPayload rayPayload) -{ - float3 worldRayDirection = WorldRayDirection(); - - // View-independent background gradient to simulate a basic sky background - const float3 gradientStart = float3(0.5, 0.6, 1.0); - const float3 gradientEnd = float3(1.0, 1.0, 1.0); - float3 unitDir = normalize(worldRayDirection); - float t = 0.5 * (unitDir.y + 1.0); - rayPayload.color = (1.0-t) * gradientStart + t * gradientEnd; - - rayPayload.distance = -1.0f; - rayPayload.normal = float3(0, 0, 0); - rayPayload.reflector = 0.0f; -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingreflections/miss.rmiss.spv b/shaders/hlsl/raytracingreflections/miss.rmiss.spv deleted file mode 100644 index 959cfebc..00000000 Binary files a/shaders/hlsl/raytracingreflections/miss.rmiss.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingreflections/raygen.rgen b/shaders/hlsl/raytracingreflections/raygen.rgen deleted file mode 100644 index 23d2cea8..00000000 --- a/shaders/hlsl/raytracingreflections/raygen.rgen +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2020 Google LLC - -RaytracingAccelerationStructure rs : register(t0); -RWTexture2D image : register(u1); - -struct CameraProperties -{ - float4x4 viewInverse; - float4x4 projInverse; - float4 lightPos; -}; -cbuffer cam : register(b2) { CameraProperties cam; }; - - -struct RayPayload { - float3 color; - float distance; - float3 normal; - float reflector; -}; - -// Max. number of recursion is passed via a specialization constant -[[vk::constant_id(0)]] const int MAX_RECURSION = 0; - -[shader("raygeneration")] -void main() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter/float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0,0,0,1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - float3 color = float3(0.0, 0.0, 0.0); - - for (int i = 0; i < MAX_RECURSION; i++) { - RayPayload rayPayload; - TraceRay(rs, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, rayPayload); - float3 hitColor = rayPayload.color; - - if (rayPayload.distance < 0.0f) { - color += hitColor; - break; - } else if (rayPayload.reflector == 1.0f) { - const float3 hitPos = rayDesc.Origin + rayDesc.Direction * rayPayload.distance; - rayDesc.Origin = hitPos + rayPayload.normal * 0.001f; - rayDesc.Direction = reflect(rayDesc.Direction, rayPayload.normal); - } else { - color += hitColor; - break; - } - - } - - image[int2(LaunchID.xy)] = float4(color, 0.0); -} diff --git a/shaders/hlsl/raytracingreflections/raygen.rgen.spv b/shaders/hlsl/raytracingreflections/raygen.rgen.spv deleted file mode 100644 index d95bddeb..00000000 Binary files a/shaders/hlsl/raytracingreflections/raygen.rgen.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingsbtdata/closesthit.rchit b/shaders/hlsl/raytracingsbtdata/closesthit.rchit deleted file mode 100644 index 0a670e95..00000000 --- a/shaders/hlsl/raytracingsbtdata/closesthit.rchit +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2020 Google LLC - -struct Attributes -{ - float2 bary; -}; - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -struct SBT { - float r; - float g; - float b; -}; -[[vk::shader_record_ext]] -ConstantBuffer sbt; - -[shader("closesthit")] -void main(inout Payload p, in Attributes attribs) -{ - // Update the hit value to the hit record SBT data associated with this - // geometry ID and ray ID - p.hitValue = float3(sbt.r, sbt.g, sbt.g); -} diff --git a/shaders/hlsl/raytracingsbtdata/closesthit.rchit.spv b/shaders/hlsl/raytracingsbtdata/closesthit.rchit.spv deleted file mode 100644 index 41e87ffc..00000000 Binary files a/shaders/hlsl/raytracingsbtdata/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingsbtdata/miss.rmiss b/shaders/hlsl/raytracingsbtdata/miss.rmiss deleted file mode 100644 index 6d9fad60..00000000 --- a/shaders/hlsl/raytracingsbtdata/miss.rmiss +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 Google LLC - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -struct SBT { - float r; - float g; - float b; -}; -[[vk::shader_record_ext]] -ConstantBuffer sbt; - -[shader("miss")] -void main(inout Payload p) -{ - // Update the hit value to the hit record SBT data associated with this - // miss record - p.hitValue = float3(sbt.r, sbt.g, sbt.g); -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingsbtdata/miss.rmiss.spv b/shaders/hlsl/raytracingsbtdata/miss.rmiss.spv deleted file mode 100644 index 90f3c1bf..00000000 Binary files a/shaders/hlsl/raytracingsbtdata/miss.rmiss.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingsbtdata/raygen.rgen b/shaders/hlsl/raytracingsbtdata/raygen.rgen deleted file mode 100644 index e79749c2..00000000 --- a/shaders/hlsl/raytracingsbtdata/raygen.rgen +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2020 Google LLC - -RaytracingAccelerationStructure rs : register(t0); -RWTexture2D image : register(u1); - -struct CameraProperties -{ - float4x4 viewInverse; - float4x4 projInverse; -}; -cbuffer cam : register(b2) { CameraProperties cam; }; - -struct Payload -{ -[[vk::location(0)]] float3 hitValue; -}; - -struct SBT { - float r; - float g; - float b; -}; -[[vk::shader_record_ext]] -ConstantBuffer sbt; - -[shader("raygeneration")] -void main() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter/float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0,0,0,1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - - // use border to demonstrate raygen record data - if (all(LaunchID.xy > int2(16, 16)) && all(LaunchID.xy < LaunchSize.xy - int2(16, 16))) - { - // Generate a checker board pattern to trace out rays or use hit record data - int2 pos = int2(LaunchID.xy / 16); - if (((pos.x + pos.y % 2) % 2) == 0) { - // This will set hit value to either hit or miss SBT record color - TraceRay(rs, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - } - else { - // Set the hit value to the raygen SBT data - payload.hitValue = float3(sbt.r, sbt.g, sbt.b); - } - } - else { - // Set hit value to black - payload.hitValue = float3(0.0, 0.0, 0.0); - } - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} diff --git a/shaders/hlsl/raytracingsbtdata/raygen.rgen.spv b/shaders/hlsl/raytracingsbtdata/raygen.rgen.spv deleted file mode 100644 index 7a2516cd..00000000 Binary files a/shaders/hlsl/raytracingsbtdata/raygen.rgen.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingshadows/closesthit.rchit b/shaders/hlsl/raytracingshadows/closesthit.rchit deleted file mode 100644 index 6e644ca9..00000000 --- a/shaders/hlsl/raytracingshadows/closesthit.rchit +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2020 Google LLC - -struct Payload -{ - [[vk::location(0)]] float3 hitValue; - [[vk::location(1)]] bool shadowed; -}; - -struct Attributes -{ - float2 bary; -}; - -RaytracingAccelerationStructure topLevelAS : register(t0); -struct UBO -{ - float4x4 viewInverse; - float4x4 projInverse; - float4 lightPos; - int vertexSize; -}; -cbuffer ubo : register(b2) { UBO ubo; }; - -StructuredBuffer vertices : register(t3); -StructuredBuffer indices : register(t4); - -struct Vertex -{ - float3 pos; - float3 normal; - float2 uv; - float4 color; - float4 _pad0; - float4 _pad1; -}; - -Vertex unpack(uint index) -{ - // Unpack the vertices from the SSBO using the glTF vertex structure - // The multiplier is the size of the vertex divided by four float components (=16 bytes) - const int m = ubo.vertexSize / 16; - - float4 d0 = vertices[m * index + 0]; - float4 d1 = vertices[m * index + 1]; - float4 d2 = vertices[m * index + 2]; - - Vertex v; - v.pos = d0.xyz; - v.normal = float3(d0.w, d1.x, d1.y); - v.color = float4(d2.x, d2.y, d2.z, 1.0); - - return v; -} - -[shader("closesthit")] -void main(inout Payload payload, in Attributes attribs) -{ - uint PrimitiveID = PrimitiveIndex(); - int3 index = int3(indices[3 * PrimitiveID], indices[3 * PrimitiveID + 1], indices[3 * PrimitiveID + 2]); - - Vertex v0 = unpack(index.x); - Vertex v1 = unpack(index.y); - Vertex v2 = unpack(index.z); - - // Interpolate normal - const float3 barycentricCoords = float3(1.0f - attribs.bary.x - attribs.bary.y, attribs.bary.x, attribs.bary.y); - float3 normal = normalize(v0.normal * barycentricCoords.x + v1.normal * barycentricCoords.y + v2.normal * barycentricCoords.z); - - // Basic lighting - float3 lightVector = normalize(ubo.lightPos.xyz); - float dot_product = max(dot(lightVector, normal), 0.2); - payload.hitValue = v0.color.rgb * dot_product; - - RayDesc rayDesc; - rayDesc.Origin = WorldRayOrigin() + WorldRayDirection() * RayTCurrent(); - rayDesc.Direction = lightVector; - rayDesc.TMin = 0.001; - rayDesc.TMax = 100.0; - - payload.shadowed = true; - // Offset indices to match shadow hit/miss index - TraceRay(topLevelAS, RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_CLOSEST_HIT_SHADER, 0xff, 0, 0, 1, rayDesc, payload); - if (payload.shadowed) { - payload.hitValue *= 0.3; - } -} diff --git a/shaders/hlsl/raytracingshadows/closesthit.rchit.spv b/shaders/hlsl/raytracingshadows/closesthit.rchit.spv deleted file mode 100644 index 4f6ff0a6..00000000 Binary files a/shaders/hlsl/raytracingshadows/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingshadows/miss.rmiss b/shaders/hlsl/raytracingshadows/miss.rmiss deleted file mode 100644 index e4193639..00000000 --- a/shaders/hlsl/raytracingshadows/miss.rmiss +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2020 Google LLC - -struct Payload -{ - [[vk::location(0)]] float3 hitValue; - [[vk::location(1)]] bool shadowed; -}; - -[shader("miss")] -void main(inout Payload payload) -{ - payload.hitValue = float3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingshadows/miss.rmiss.spv b/shaders/hlsl/raytracingshadows/miss.rmiss.spv deleted file mode 100644 index 999bf108..00000000 Binary files a/shaders/hlsl/raytracingshadows/miss.rmiss.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingshadows/raygen.rgen b/shaders/hlsl/raytracingshadows/raygen.rgen deleted file mode 100644 index 0ccf0e44..00000000 --- a/shaders/hlsl/raytracingshadows/raygen.rgen +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2020 Google LLC - -RaytracingAccelerationStructure rs : register(t0); -RWTexture2D image : register(u1); - -struct CameraProperties -{ - float4x4 viewInverse; - float4x4 projInverse; - float4 lightPos; -}; -cbuffer cam : register(b2) { CameraProperties cam; }; - -struct Payload -{ - [[vk::location(0)]] float3 hitValue; -}; - -[shader("raygeneration")] -void main() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter/float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0,0,0,1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - TraceRay(rs, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} diff --git a/shaders/hlsl/raytracingshadows/raygen.rgen.spv b/shaders/hlsl/raytracingshadows/raygen.rgen.spv deleted file mode 100644 index ffc2f8a8..00000000 Binary files a/shaders/hlsl/raytracingshadows/raygen.rgen.spv and /dev/null differ diff --git a/shaders/hlsl/raytracingshadows/shadow.rmiss b/shaders/hlsl/raytracingshadows/shadow.rmiss deleted file mode 100644 index 3dfbb647..00000000 --- a/shaders/hlsl/raytracingshadows/shadow.rmiss +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2020 Google LLC - -struct Payload -{ - [[vk::location(0)]] float3 hitValue; - [[vk::location(1)]] bool shadowed; -}; - -[shader("miss")] -void main(inout Payload payload) -{ - payload.shadowed = false; -} \ No newline at end of file diff --git a/shaders/hlsl/raytracingshadows/shadow.rmiss.spv b/shaders/hlsl/raytracingshadows/shadow.rmiss.spv deleted file mode 100644 index 32afce08..00000000 Binary files a/shaders/hlsl/raytracingshadows/shadow.rmiss.spv and /dev/null differ diff --git a/shaders/hlsl/renderheadless/triangle.frag b/shaders/hlsl/renderheadless/triangle.frag deleted file mode 100644 index 8a7faf06..00000000 --- a/shaders/hlsl/renderheadless/triangle.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main([[vk::location(0)]] float3 Color : COLOR0) : SV_TARGET -{ - return float4(Color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/renderheadless/triangle.frag.spv b/shaders/hlsl/renderheadless/triangle.frag.spv deleted file mode 100644 index 870fb6c1..00000000 Binary files a/shaders/hlsl/renderheadless/triangle.frag.spv and /dev/null differ diff --git a/shaders/hlsl/renderheadless/triangle.vert b/shaders/hlsl/renderheadless/triangle.vert deleted file mode 100644 index 6e5c2207..00000000 --- a/shaders/hlsl/renderheadless/triangle.vert +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Color : COLOR0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -}; - -struct PushConsts { - float4x4 mvp; -}; -[[vk::push_constant]] PushConsts pushConsts; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Pos = mul(pushConsts.mvp, float4(input.Pos.xyz, 1.0)); - return output; -} diff --git a/shaders/hlsl/renderheadless/triangle.vert.spv b/shaders/hlsl/renderheadless/triangle.vert.spv deleted file mode 100644 index 8598544f..00000000 Binary files a/shaders/hlsl/renderheadless/triangle.vert.spv and /dev/null differ diff --git a/shaders/hlsl/screenshot/mesh.frag b/shaders/hlsl/screenshot/mesh.frag deleted file mode 100644 index 2c14be89..00000000 --- a/shaders/hlsl/screenshot/mesh.frag +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.1, 0.1, 0.1); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/screenshot/mesh.frag.spv b/shaders/hlsl/screenshot/mesh.frag.spv deleted file mode 100644 index 6966e9ad..00000000 Binary files a/shaders/hlsl/screenshot/mesh.frag.spv and /dev/null differ diff --git a/shaders/hlsl/screenshot/mesh.vert b/shaders/hlsl/screenshot/mesh.vert deleted file mode 100644 index 38f9bc79..00000000 --- a/shaders/hlsl/screenshot/mesh.vert +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos))); - - float4 pos = mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - output.Normal = mul((float3x3)ubo.model, input.Normal); - - float3 lightPos = float3(1.0f, -1.0f, 1.0f); - output.LightVec = lightPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} diff --git a/shaders/hlsl/screenshot/mesh.vert.spv b/shaders/hlsl/screenshot/mesh.vert.spv deleted file mode 100644 index 76f9ef3d..00000000 Binary files a/shaders/hlsl/screenshot/mesh.vert.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmapping/offscreen.frag b/shaders/hlsl/shadowmapping/offscreen.frag deleted file mode 100644 index 54d4ac24..00000000 --- a/shaders/hlsl/shadowmapping/offscreen.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main() : SV_TARGET -{ - return float4(1.0, 0.0, 0.0, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/shadowmapping/offscreen.frag.spv b/shaders/hlsl/shadowmapping/offscreen.frag.spv deleted file mode 100644 index edf3c6e0..00000000 Binary files a/shaders/hlsl/shadowmapping/offscreen.frag.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmapping/offscreen.vert b/shaders/hlsl/shadowmapping/offscreen.vert deleted file mode 100644 index b20b1d1f..00000000 --- a/shaders/hlsl/shadowmapping/offscreen.vert +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2020 Google LLC - -struct UBO -{ - float4x4 depthMVP; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -float4 main([[vk::location(0)]] float3 Pos : POSITION0) : SV_POSITION -{ - return mul(ubo.depthMVP, float4(Pos, 1.0)); -} \ No newline at end of file diff --git a/shaders/hlsl/shadowmapping/offscreen.vert.spv b/shaders/hlsl/shadowmapping/offscreen.vert.spv deleted file mode 100644 index 3c5406dc..00000000 Binary files a/shaders/hlsl/shadowmapping/offscreen.vert.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmapping/quad.frag b/shaders/hlsl/shadowmapping/quad.frag deleted file mode 100644 index 419f9569..00000000 --- a/shaders/hlsl/shadowmapping/quad.frag +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4x4 lightSpace; - float4 lightPos; - float zNear; - float zFar; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -float LinearizeDepth(float depth) -{ - float n = ubo.zNear; - float f = ubo.zFar; - float z = depth; - return (2.0 * n) / (f + n - z * (f - n)); -} - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - float depth = textureColor.Sample(samplerColor, inUV).r; - return float4((1.0-LinearizeDepth(depth)).xxx, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/shadowmapping/quad.frag.spv b/shaders/hlsl/shadowmapping/quad.frag.spv deleted file mode 100644 index c7fda72a..00000000 Binary files a/shaders/hlsl/shadowmapping/quad.frag.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmapping/quad.vert b/shaders/hlsl/shadowmapping/quad.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/shadowmapping/quad.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/shadowmapping/quad.vert.spv b/shaders/hlsl/shadowmapping/quad.vert.spv deleted file mode 100644 index 8754eaa1..00000000 Binary files a/shaders/hlsl/shadowmapping/quad.vert.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmapping/scene.frag b/shaders/hlsl/shadowmapping/scene.frag deleted file mode 100644 index 5ae6167d..00000000 --- a/shaders/hlsl/shadowmapping/scene.frag +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D shadowMapTexture : register(t1); -SamplerState shadowMapSampler : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -[[vk::location(4)]] float4 ShadowCoord : TEXCOORD3; -}; - -[[vk::constant_id(0)]] const int enablePCF = 0; - -#define ambient 0.1 - -float textureProj(float4 shadowCoord, float2 off) -{ - float shadow = 1.0; - if ( shadowCoord.z > -1.0 && shadowCoord.z < 1.0 ) - { - float dist = shadowMapTexture.Sample( shadowMapSampler, shadowCoord.xy + off ).r; - if ( shadowCoord.w > 0.0 && dist < shadowCoord.z ) - { - shadow = ambient; - } - } - return shadow; -} - -float filterPCF(float4 sc) -{ - int2 texDim; - shadowMapTexture.GetDimensions(texDim.x, texDim.y); - float scale = 1.5; - float dx = scale * 1.0 / float(texDim.x); - float dy = scale * 1.0 / float(texDim.y); - - float shadowFactor = 0.0; - int count = 0; - int range = 1; - - for (int x = -range; x <= range; x++) - { - for (int y = -range; y <= range; y++) - { - shadowFactor += textureProj(sc, float2(dx*x, dy*y)); - count++; - } - - } - return shadowFactor / count; -} - -float4 main(VSOutput input) : SV_TARGET -{ - float shadow = (enablePCF == 1) ? filterPCF(input.ShadowCoord / input.ShadowCoord.w) : textureProj(input.ShadowCoord / input.ShadowCoord.w, float2(0.0, 0.0)); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = normalize(-reflect(L, N)); - float3 diffuse = max(dot(N, L), ambient) * input.Color; - - return float4(diffuse * shadow, 1.0); -} diff --git a/shaders/hlsl/shadowmapping/scene.frag.spv b/shaders/hlsl/shadowmapping/scene.frag.spv deleted file mode 100644 index 893c37ba..00000000 Binary files a/shaders/hlsl/shadowmapping/scene.frag.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmapping/scene.vert b/shaders/hlsl/shadowmapping/scene.vert deleted file mode 100644 index 30ad6138..00000000 --- a/shaders/hlsl/shadowmapping/scene.vert +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4x4 lightSpace; - float4 lightPos; - float zNear; - float zFar; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -[[vk::location(4)]] float4 ShadowCoord : TEXCOORD3; -}; - -static const float4x4 biasMat = float4x4( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 ); - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Normal = input.Normal; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.LightVec = normalize(ubo.lightPos.xyz - input.Pos); - output.ViewVec = -pos.xyz; - - output.ShadowCoord = mul(biasMat, mul(ubo.lightSpace, mul(ubo.model, float4(input.Pos, 1.0)))); - return output; -} - diff --git a/shaders/hlsl/shadowmapping/scene.vert.spv b/shaders/hlsl/shadowmapping/scene.vert.spv deleted file mode 100644 index 8e1c467f..00000000 Binary files a/shaders/hlsl/shadowmapping/scene.vert.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingcascade/debugshadowmap.frag b/shaders/hlsl/shadowmappingcascade/debugshadowmap.frag deleted file mode 100644 index 32871804..00000000 --- a/shaders/hlsl/shadowmappingcascade/debugshadowmap.frag +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2DArray shadowMapTexture : register(t1); -SamplerState shadowMapSampler : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] uint CascadeIndex : TEXCOORD1; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float depth = shadowMapTexture.Sample(shadowMapSampler, float3(input.UV, float(input.CascadeIndex))).r; - return float4(depth.xxx, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/shadowmappingcascade/debugshadowmap.frag.spv b/shaders/hlsl/shadowmappingcascade/debugshadowmap.frag.spv deleted file mode 100644 index 9af8e160..00000000 Binary files a/shaders/hlsl/shadowmappingcascade/debugshadowmap.frag.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingcascade/debugshadowmap.vert b/shaders/hlsl/shadowmappingcascade/debugshadowmap.vert deleted file mode 100644 index 6e8ae835..00000000 --- a/shaders/hlsl/shadowmappingcascade/debugshadowmap.vert +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2020 Google LLC - -struct PushConsts { - float4 position; - uint cascadeIndex; -}; -[[vk::push_constant]] PushConsts pushConsts; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] uint CascadeIndex : TEXCOORD1; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.CascadeIndex = pushConsts.cascadeIndex; - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/shadowmappingcascade/debugshadowmap.vert.spv b/shaders/hlsl/shadowmappingcascade/debugshadowmap.vert.spv deleted file mode 100644 index c4178cc5..00000000 Binary files a/shaders/hlsl/shadowmappingcascade/debugshadowmap.vert.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingcascade/depthpass.frag b/shaders/hlsl/shadowmappingcascade/depthpass.frag deleted file mode 100644 index 43939200..00000000 --- a/shaders/hlsl/shadowmappingcascade/depthpass.frag +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D colorMapTexture : register(t0, space1); -SamplerState colorMapSampler : register(s0, space1); - -void main([[vk::location(0)]] float2 inUV : TEXCOORD0) -{ - float alpha = colorMapTexture.Sample(colorMapSampler, inUV).a; - if (alpha < 0.5) { - clip(-1); - } -} \ No newline at end of file diff --git a/shaders/hlsl/shadowmappingcascade/depthpass.frag.spv b/shaders/hlsl/shadowmappingcascade/depthpass.frag.spv deleted file mode 100644 index fb4495e5..00000000 Binary files a/shaders/hlsl/shadowmappingcascade/depthpass.frag.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingcascade/depthpass.vert b/shaders/hlsl/shadowmappingcascade/depthpass.vert deleted file mode 100644 index b2e848a0..00000000 --- a/shaders/hlsl/shadowmappingcascade/depthpass.vert +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2024 Sascha Willems - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; -// todo: pass via specialization constant -#define SHADOW_MAP_CASCADE_COUNT 4 - -struct PushConsts { - float4 position; - uint cascadeIndex; -}; -[[vk::push_constant]] PushConsts pushConsts; - -struct UBO { - float4x4 cascadeViewProjMat[SHADOW_MAP_CASCADE_COUNT]; -}; -cbuffer ubo : register(b3) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - float3 pos = input.Pos + pushConsts.position.xyz; - output.Pos = mul(ubo.cascadeViewProjMat[pushConsts.cascadeIndex], float4(pos, 1.0)); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/shadowmappingcascade/depthpass.vert.spv b/shaders/hlsl/shadowmappingcascade/depthpass.vert.spv deleted file mode 100644 index bb202835..00000000 Binary files a/shaders/hlsl/shadowmappingcascade/depthpass.vert.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingcascade/scene.frag b/shaders/hlsl/shadowmappingcascade/scene.frag deleted file mode 100644 index b02919ca..00000000 --- a/shaders/hlsl/shadowmappingcascade/scene.frag +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2024 Sascha Willems - -#define SHADOW_MAP_CASCADE_COUNT 4 - -Texture2DArray shadowMapTexture : register(t1); -SamplerState shadowMapSampler : register(s1); -Texture2D colorMapTexture : register(t0, space1); -SamplerState colorMapSampler : register(s0, space1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewPos : POSITION1; -[[vk::location(3)]] float3 Pos : POSITION0; -[[vk::location(4)]] float2 UV : TEXCOORD0; -}; - -[[vk::constant_id(0)]] const int enablePCF = 0; - -#define ambient 0.3 - -struct UBO { - float4 cascadeSplits; - float4x4 inverseViewMat; - float3 lightDir; - float _pad; - int colorCascades; -}; -cbuffer ubo : register(b2) { UBO ubo; }; - -struct CVPM { - float4x4 matrices[SHADOW_MAP_CASCADE_COUNT]; -}; -cbuffer cascadeViewProjMatrices : register(b3) { CVPM cascadeViewProjMatrices; } - -static const float4x4 biasMat = float4x4( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 -); - -float textureProj(float4 shadowCoord, float2 offset, uint cascadeIndex) -{ - float shadow = 1.0; - float bias = 0.005; - - if ( shadowCoord.z > -1.0 && shadowCoord.z < 1.0 ) { - float dist = shadowMapTexture.Sample(shadowMapSampler, float3(shadowCoord.xy + offset, cascadeIndex)).r; - if (shadowCoord.w > 0 && dist < shadowCoord.z - bias) { - shadow = ambient; - } - } - return shadow; - -} - -float filterPCF(float4 sc, uint cascadeIndex) -{ - int3 texDim; - shadowMapTexture.GetDimensions(texDim.x, texDim.y, texDim.z); - float scale = 0.75; - float dx = scale * 1.0 / float(texDim.x); - float dy = scale * 1.0 / float(texDim.y); - - float shadowFactor = 0.0; - int count = 0; - int range = 1; - - for (int x = -range; x <= range; x++) { - for (int y = -range; y <= range; y++) { - shadowFactor += textureProj(sc, float2(dx*x, dy*y), cascadeIndex); - count++; - } - } - return shadowFactor / count; -} - -float4 main(VSOutput input) : SV_TARGET -{ - float4 outFragColor; - float4 color = colorMapTexture.Sample(colorMapSampler, input.UV); - if (color.a < 0.5) { - clip(-1); - } - - // Get cascade index for the current fragment's view position - uint cascadeIndex = 0; - for(uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i) { - if(input.ViewPos.z < ubo.cascadeSplits[i]) { - cascadeIndex = i + 1; - } - } - - // Depth compare for shadowing - float4 shadowCoord = mul(biasMat, mul(cascadeViewProjMatrices.matrices[cascadeIndex], float4(input.Pos, 1.0))); - - float shadow = 0; - if (enablePCF == 1) { - shadow = filterPCF(shadowCoord / shadowCoord.w, cascadeIndex); - } else { - shadow = textureProj(shadowCoord / shadowCoord.w, float2(0.0, 0.0), cascadeIndex); - } - - // Directional light - float3 N = normalize(input.Normal); - float3 L = normalize(-ubo.lightDir); - float3 H = normalize(L + input.ViewPos); - float diffuse = max(dot(N, L), ambient); - float3 lightColor = float3(1.0, 1.0, 1.0); - outFragColor.rgb = max(lightColor * (diffuse * color.rgb), float3(0.0, 0.0, 0.0)); - outFragColor.rgb *= shadow; - outFragColor.a = color.a; - - // Color cascades (if enabled) - if (ubo.colorCascades == 1) { - switch(cascadeIndex) { - case 0 : - outFragColor.rgb *= float3(1.0f, 0.25f, 0.25f); - break; - case 1 : - outFragColor.rgb *= float3(0.25f, 1.0f, 0.25f); - break; - case 2 : - outFragColor.rgb *= float3(0.25f, 0.25f, 1.0f); - break; - case 3 : - outFragColor.rgb *= float3(1.0f, 1.0f, 0.25f); - break; - } - } - - return outFragColor; -} diff --git a/shaders/hlsl/shadowmappingcascade/scene.frag.spv b/shaders/hlsl/shadowmappingcascade/scene.frag.spv deleted file mode 100644 index 100717b3..00000000 Binary files a/shaders/hlsl/shadowmappingcascade/scene.frag.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingcascade/scene.vert b/shaders/hlsl/shadowmappingcascade/scene.vert deleted file mode 100644 index 957845b2..00000000 --- a/shaders/hlsl/shadowmappingcascade/scene.vert +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 Normal : NORMAL0; -}; - -struct UBO { - float4x4 projection; - float4x4 view; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewPos : POSITION1; -[[vk::location(3)]] float3 WorldPos : POSITION0; -[[vk::location(4)]] float2 UV : TEXCOORD0; -}; - -struct PushConsts { - float4 position; - uint cascadeIndex; -}; -[[vk::push_constant]] PushConsts pushConsts; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Normal = input.Normal; - output.UV = input.UV; - float3 pos = input.Pos + pushConsts.position.xyz; - output.WorldPos = pos; - output.ViewPos = mul(ubo.view, float4(pos.xyz, 1.0)).xyz; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(pos.xyz, 1.0)))); - return output; -} - diff --git a/shaders/hlsl/shadowmappingcascade/scene.vert.spv b/shaders/hlsl/shadowmappingcascade/scene.vert.spv deleted file mode 100644 index 7875e028..00000000 Binary files a/shaders/hlsl/shadowmappingcascade/scene.vert.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingomni/cubemapdisplay.frag b/shaders/hlsl/shadowmappingomni/cubemapdisplay.frag deleted file mode 100644 index 7e8bdc77..00000000 --- a/shaders/hlsl/shadowmappingomni/cubemapdisplay.frag +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube shadowCubeMapTexture : register(t1); -SamplerState shadowCubeMapSampler : register(s1); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - float4 outFragColor = float4(0, 0, 0, 0); - outFragColor.rgb = float3(0.05, 0.05, 0.05); - - float3 samplePos = float3(0, 0, 0); - - // Crude statement to visualize different cube map faces based on UV coordinates - int x = int(floor(inUV.x / 0.25f)); - int y = int(floor(inUV.y / (1.0 / 3.0))); - if (y == 1) { - float2 uv = float2(inUV.x * 4.0f, (inUV.y - 1.0/3.0) * 3.0); - uv = 2.0 * float2(uv.x - float(x) * 1.0, uv.y) - 1.0; - switch (x) { - case 0: // NEGATIVE_X - samplePos = float3(-1.0f, uv.y, uv.x); - break; - case 1: // POSITIVE_Z - samplePos = float3(uv.x, uv.y, 1.0f); - break; - case 2: // POSITIVE_X - samplePos = float3(1.0, uv.y, -uv.x); - break; - case 3: // NEGATIVE_Z - samplePos = float3(-uv.x, uv.y, -1.0f); - break; - } - } else { - if (x == 1) { - float2 uv = float2((inUV.x - 0.25) * 4.0, (inUV.y - float(y) / 3.0) * 3.0); - uv = 2.0 * uv - 1.0; - switch (y) { - case 0: // NEGATIVE_Y - samplePos = float3(uv.x, -1.0f, uv.y); - break; - case 2: // POSITIVE_Y - samplePos = float3(uv.x, 1.0f, -uv.y); - break; - } - } - } - - if ((samplePos.x != 0.0f) && (samplePos.y != 0.0f)) { - float dist = length(shadowCubeMapTexture.Sample(shadowCubeMapSampler, samplePos).xyz) * 0.005; - outFragColor = float4(dist.xxx, 1.0); - } - return outFragColor; -} \ No newline at end of file diff --git a/shaders/hlsl/shadowmappingomni/cubemapdisplay.frag.spv b/shaders/hlsl/shadowmappingomni/cubemapdisplay.frag.spv deleted file mode 100644 index c448af9b..00000000 Binary files a/shaders/hlsl/shadowmappingomni/cubemapdisplay.frag.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingomni/cubemapdisplay.vert b/shaders/hlsl/shadowmappingomni/cubemapdisplay.vert deleted file mode 100644 index 41068e73..00000000 --- a/shaders/hlsl/shadowmappingomni/cubemapdisplay.vert +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 Google LLC - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV.xy * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - diff --git a/shaders/hlsl/shadowmappingomni/cubemapdisplay.vert.spv b/shaders/hlsl/shadowmappingomni/cubemapdisplay.vert.spv deleted file mode 100644 index 8754eaa1..00000000 Binary files a/shaders/hlsl/shadowmappingomni/cubemapdisplay.vert.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingomni/offscreen.frag b/shaders/hlsl/shadowmappingomni/offscreen.frag deleted file mode 100644 index 82c9fa9b..00000000 --- a/shaders/hlsl/shadowmappingomni/offscreen.frag +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 LightPos : POSITION1; -}; - -float main(VSOutput input) : SV_TARGET -{ - // Store distance to light as 32 bit float value - float3 lightVec = input.Pos.xyz - input.LightPos; - return length(lightVec); -} \ No newline at end of file diff --git a/shaders/hlsl/shadowmappingomni/offscreen.frag.spv b/shaders/hlsl/shadowmappingomni/offscreen.frag.spv deleted file mode 100644 index 36577de8..00000000 Binary files a/shaders/hlsl/shadowmappingomni/offscreen.frag.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingomni/offscreen.vert b/shaders/hlsl/shadowmappingomni/offscreen.vert deleted file mode 100644 index 3c504104..00000000 --- a/shaders/hlsl/shadowmappingomni/offscreen.vert +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float4 WorldPos : POSITION0; -[[vk::location(1)]] float3 LightPos : POSITION1; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct PushConsts -{ - float4x4 view; -}; -[[vk::push_constant]] PushConsts pushConsts; - -VSOutput main([[vk::location(0)]] float3 Pos : POSITION0) -{ - VSOutput output = (VSOutput)0; - output.Pos = mul(ubo.projection, mul(pushConsts.view, mul(ubo.model, float4(Pos, 1.0)))); - - output.WorldPos = float4(Pos, 1.0); - output.LightPos = ubo.lightPos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/shadowmappingomni/offscreen.vert.spv b/shaders/hlsl/shadowmappingomni/offscreen.vert.spv deleted file mode 100644 index b6db5f0e..00000000 Binary files a/shaders/hlsl/shadowmappingomni/offscreen.vert.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingomni/scene.frag b/shaders/hlsl/shadowmappingomni/scene.frag deleted file mode 100644 index 840d8298..00000000 --- a/shaders/hlsl/shadowmappingomni/scene.frag +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube shadowCubeMapTexture : register(t1); -SamplerState shadowCubeMapSampler : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 EyePos : POSITION0; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -[[vk::location(4)]] float3 WorldPos : POSITION1; -[[vk::location(5)]] float3 LightPos : POSITION2; -}; - -#define EPSILON 0.15 -#define SHADOW_OPACITY 0.5 - -float4 main(VSOutput input) : SV_TARGET -{ - // Lighting - float3 N = normalize(input.Normal); - float3 L = normalize(float3(1.0, 1.0, 1.0)); - - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - - float4 IAmbient = float4(float3(0.05, 0.05, 0.05), 1.0); - float4 IDiffuse = float4(1.0, 1.0, 1.0, 1.0) * max(dot(input.Normal, input.LightVec), 0.0); - - float4 outFragColor = float4(IAmbient + IDiffuse * float4(input.Color, 1.0)); - - // Shadow - float3 lightVec = input.WorldPos - input.LightPos; - float sampledDist = shadowCubeMapTexture.Sample(shadowCubeMapSampler, lightVec).r; - float dist = length(lightVec); - - // Check if fragment is in shadow - float shadow = (dist <= sampledDist + EPSILON) ? 1.0 : SHADOW_OPACITY; - - outFragColor.rgb *= shadow; - return outFragColor; -} \ No newline at end of file diff --git a/shaders/hlsl/shadowmappingomni/scene.frag.spv b/shaders/hlsl/shadowmappingomni/scene.frag.spv deleted file mode 100644 index 19301a3a..00000000 Binary files a/shaders/hlsl/shadowmappingomni/scene.frag.spv and /dev/null differ diff --git a/shaders/hlsl/shadowmappingomni/scene.vert b/shaders/hlsl/shadowmappingomni/scene.vert deleted file mode 100644 index be1915a7..00000000 --- a/shaders/hlsl/shadowmappingomni/scene.vert +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 EyePos : POSITION0; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -[[vk::location(4)]] float3 WorldPos : POSITION1; -[[vk::location(5)]] float3 LightPos : POSITION2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Normal = input.Normal; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - output.EyePos = mul(ubo.model, float4(input.Pos, 1.0f)).xyz; - output.LightVec = normalize(ubo.lightPos.xyz - input.Pos.xyz); - output.WorldPos = input.Pos; - - output.LightPos = ubo.lightPos.xyz; - return output; -} - diff --git a/shaders/hlsl/shadowmappingomni/scene.vert.spv b/shaders/hlsl/shadowmappingomni/scene.vert.spv deleted file mode 100644 index 58e5ddc8..00000000 Binary files a/shaders/hlsl/shadowmappingomni/scene.vert.spv and /dev/null differ diff --git a/shaders/hlsl/specializationconstants/uber.frag b/shaders/hlsl/specializationconstants/uber.frag deleted file mode 100644 index 57ac65e6..00000000 --- a/shaders/hlsl/specializationconstants/uber.frag +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColormap : register(t1); -SamplerState samplerColormap : register(s1); -Texture2D textureDiscard : register(t2); -SamplerState samplerDiscard : register(s2); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -// We use this constant to control the flow of the shader depending on the -// lighting model selected at pipeline creation time -[[vk::constant_id(0)]] const int LIGHTING_MODEL = 0; -// Parameter for the toon shading part of the shader -[[vk::constant_id(1)]] const /*float*/int PARAM_TOON_DESATURATION = 0.0f; - -float4 main(VSOutput input) : SV_TARGET -{ - switch (LIGHTING_MODEL) { - case 0: // Phong - { - float3 ambient = input.Color * float3(0.25, 0.25, 0.25); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 32.0) * float3(0.75, 0.75, 0.75); - return float4(ambient + diffuse * 1.75 + specular, 1.0); - } - case 1: // Toon - { - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float intensity = dot(N,L); - float3 color; - if (intensity > 0.98) - color = input.Color * 1.5; - else if (intensity > 0.9) - color = input.Color * 1.0; - else if (intensity > 0.5) - color = input.Color * 0.6; - else if (intensity > 0.25) - color = input.Color * 0.4; - else - color = input.Color * 0.2; - // Desaturate a bit - color = float3(lerp(color, dot(float3(0.2126,0.7152,0.0722), color).xxx, asfloat(PARAM_TOON_DESATURATION))); - return float4(color, 1); - } - case 2: // Textured - { - float4 color = textureColormap.Sample(samplerColormap, input.UV).rrra; - float3 ambient = color.rgb * float3(0.25, 0.25, 0.25) * input.Color; - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color.rgb; - float specular = pow(max(dot(R, V), 0.0), 32.0) * color.a; - return float4(ambient + diffuse + specular.xxx, 1.0); - } - } - - return float4(0, 0, 0, 0); -} \ No newline at end of file diff --git a/shaders/hlsl/specializationconstants/uber.frag.spv b/shaders/hlsl/specializationconstants/uber.frag.spv deleted file mode 100644 index f864deba..00000000 Binary files a/shaders/hlsl/specializationconstants/uber.frag.spv and /dev/null differ diff --git a/shaders/hlsl/specializationconstants/uber.vert b/shaders/hlsl/specializationconstants/uber.vert deleted file mode 100644 index 2ea7b03b..00000000 --- a/shaders/hlsl/specializationconstants/uber.vert +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/specializationconstants/uber.vert.spv b/shaders/hlsl/specializationconstants/uber.vert.spv deleted file mode 100644 index 38769e28..00000000 Binary files a/shaders/hlsl/specializationconstants/uber.vert.spv and /dev/null differ diff --git a/shaders/hlsl/sphericalenvmapping/sem.frag b/shaders/hlsl/sphericalenvmapping/sem.frag deleted file mode 100644 index 7bee1db6..00000000 --- a/shaders/hlsl/sphericalenvmapping/sem.frag +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2DArray matCapTexture : register(t1); -SamplerState matCapSampler : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Color : COLOR0; -[[vk::location(1)]] float3 EyePos : POSITION0; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] int TexIndex : TEXCOORD1; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 r = reflect( input.EyePos, input.Normal ); - float3 r2 = float3( r.x, r.y, r.z + 1.0 ); - float m = 2.0 * length( r2 ); - float2 vN = r.xy / m + .5; - return float4( matCapTexture.Sample( matCapSampler, float3(vN, input.TexIndex)).rgb * (clamp(input.Color.r * 2, 0.0, 1.0)), 1.0 ); -} diff --git a/shaders/hlsl/sphericalenvmapping/sem.frag.spv b/shaders/hlsl/sphericalenvmapping/sem.frag.spv deleted file mode 100644 index a1bb8a4a..00000000 Binary files a/shaders/hlsl/sphericalenvmapping/sem.frag.spv and /dev/null differ diff --git a/shaders/hlsl/sphericalenvmapping/sem.vert b/shaders/hlsl/sphericalenvmapping/sem.vert deleted file mode 100644 index 5514c35b..00000000 --- a/shaders/hlsl/sphericalenvmapping/sem.vert +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 normal; - float4x4 view; - int texIndex; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -[[vk::location(1)]] float3 EyePos : POSITION0; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] int TexIndex : TEXCOORD1; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - float4x4 modelView = mul(ubo.view, ubo.model); - output.EyePos = normalize( mul(modelView, input.Pos ).xyz ); - output.TexIndex = ubo.texIndex; - output.Normal = normalize( mul((float3x3)ubo.normal, input.Normal) ); - float3 r = reflect( output.EyePos, output.Normal ); - float m = 2.0 * sqrt( pow(r.x, 2.0) + pow(r.y, 2.0) + pow(r.z + 1.0, 2.0)); - output.Pos = mul(ubo.projection, mul(modelView, input.Pos)); - return output; -} diff --git a/shaders/hlsl/sphericalenvmapping/sem.vert.spv b/shaders/hlsl/sphericalenvmapping/sem.vert.spv deleted file mode 100644 index 313387a5..00000000 Binary files a/shaders/hlsl/sphericalenvmapping/sem.vert.spv and /dev/null differ diff --git a/shaders/hlsl/ssao/blur.frag b/shaders/hlsl/ssao/blur.frag deleted file mode 100644 index f0ce9234..00000000 --- a/shaders/hlsl/ssao/blur.frag +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureSSAO : register(t0); -SamplerState samplerSSAO : register(s0); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - const int blurRange = 2; - int n = 0; - int2 texDim; - textureSSAO.GetDimensions(texDim.x, texDim.y); - float2 texelSize = 1.0 / (float2)texDim; - float result = 0.0; - for (int x = -blurRange; x <= blurRange; x++) - { - for (int y = -blurRange; y <= blurRange; y++) - { - float2 offset = float2(float(x), float(y)) * texelSize; - result += textureSSAO.Sample(samplerSSAO, inUV + offset).r; - n++; - } - } - return result / (float(n)); -} \ No newline at end of file diff --git a/shaders/hlsl/ssao/blur.frag.spv b/shaders/hlsl/ssao/blur.frag.spv deleted file mode 100644 index cf2ea7e5..00000000 Binary files a/shaders/hlsl/ssao/blur.frag.spv and /dev/null differ diff --git a/shaders/hlsl/ssao/composition.frag b/shaders/hlsl/ssao/composition.frag deleted file mode 100644 index b89db525..00000000 --- a/shaders/hlsl/ssao/composition.frag +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureposition : register(t0); -SamplerState samplerposition : register(s0); -Texture2D textureNormal : register(t1); -SamplerState samplerNormal : register(s1); -Texture2D textureAlbedo : register(t2); -SamplerState samplerAlbedo : register(s2); -Texture2D textureSSAO : register(t3); -SamplerState samplerSSAO : register(s3); -Texture2D textureSSAOBlur : register(t4); -SamplerState samplerSSAOBlur : register(s4); -struct UBO -{ - float4x4 _dummy; - int ssao; - int ssaoOnly; - int ssaoBlur; -}; -cbuffer uboParams : register(b5) { UBO uboParams; }; - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - float3 fragPos = textureposition.Sample(samplerposition, inUV).rgb; - float3 normal = normalize(textureNormal.Sample(samplerNormal, inUV).rgb * 2.0 - 1.0); - float4 albedo = textureAlbedo.Sample(samplerAlbedo, inUV); - - float ssao = (uboParams.ssaoBlur == 1) ? textureSSAOBlur.Sample(samplerSSAOBlur, inUV).r : textureSSAO.Sample(samplerSSAO, inUV).r; - - float3 lightPos = float3(0.0, 0.0, 0.0); - float3 L = normalize(lightPos - fragPos); - float NdotL = max(0.5, dot(normal, L)); - - float4 outFragColor; - if (uboParams.ssaoOnly == 1) - { - outFragColor.rgb = ssao.rrr; - } - else - { - float3 baseColor = albedo.rgb * NdotL; - - if (uboParams.ssao == 1) - { - outFragColor.rgb = ssao.rrr; - - if (uboParams.ssaoOnly != 1) - outFragColor.rgb *= baseColor; - } - else - { - outFragColor.rgb = baseColor; - } - } - return outFragColor; -} \ No newline at end of file diff --git a/shaders/hlsl/ssao/composition.frag.spv b/shaders/hlsl/ssao/composition.frag.spv deleted file mode 100644 index ba67a68d..00000000 Binary files a/shaders/hlsl/ssao/composition.frag.spv and /dev/null differ diff --git a/shaders/hlsl/ssao/fullscreen.vert b/shaders/hlsl/ssao/fullscreen.vert deleted file mode 100644 index b13c2bf2..00000000 --- a/shaders/hlsl/ssao/fullscreen.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/hlsl/ssao/fullscreen.vert.spv b/shaders/hlsl/ssao/fullscreen.vert.spv deleted file mode 100644 index 46c4b31f..00000000 Binary files a/shaders/hlsl/ssao/fullscreen.vert.spv and /dev/null differ diff --git a/shaders/hlsl/ssao/gbuffer.frag b/shaders/hlsl/ssao/gbuffer.frag deleted file mode 100644 index 6b59dd50..00000000 --- a/shaders/hlsl/ssao/gbuffer.frag +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 WorldPos : POSITION0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float nearPlane; - float farPlane; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -Texture2D textureColorMap : register(t0, space1); -SamplerState samplerColorMap : register(s0, space1); - -struct FSOutput -{ - float4 Position : SV_TARGET0; - float4 Normal : SV_TARGET1; - float4 Albedo : SV_TARGET2; -}; - -float linearDepth(float depth) -{ - float z = depth * 2.0f - 1.0f; - return (2.0f * ubo.nearPlane * ubo.farPlane) / (ubo.farPlane + ubo.nearPlane - z * (ubo.farPlane - ubo.nearPlane)); -} - -FSOutput main(VSOutput input) -{ - FSOutput output = (FSOutput)0; - output.Position = float4(input.WorldPos, linearDepth(input.Pos.z)); - output.Normal = float4(normalize(input.Normal) * 0.5 + 0.5, 1.0); - output.Albedo = textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/ssao/gbuffer.frag.spv b/shaders/hlsl/ssao/gbuffer.frag.spv deleted file mode 100644 index 8ab0e21d..00000000 Binary files a/shaders/hlsl/ssao/gbuffer.frag.spv and /dev/null differ diff --git a/shaders/hlsl/ssao/gbuffer.vert b/shaders/hlsl/ssao/gbuffer.vert deleted file mode 100644 index 85f7e07d..00000000 --- a/shaders/hlsl/ssao/gbuffer.vert +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 WorldPos : POSITION0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos))); - - output.UV = input.UV; - - // Vertex position in view space - output.WorldPos = mul(ubo.view, mul(ubo.model, input.Pos)).xyz; - - // Normal in view space - float3x3 normalMatrix = (float3x3)mul(ubo.view, ubo.model); - output.Normal = mul(normalMatrix, input.Normal); - - output.Color = input.Color; - return output; -} diff --git a/shaders/hlsl/ssao/gbuffer.vert.spv b/shaders/hlsl/ssao/gbuffer.vert.spv deleted file mode 100644 index b862daa7..00000000 Binary files a/shaders/hlsl/ssao/gbuffer.vert.spv and /dev/null differ diff --git a/shaders/hlsl/ssao/ssao.frag b/shaders/hlsl/ssao/ssao.frag deleted file mode 100644 index 7bb49681..00000000 --- a/shaders/hlsl/ssao/ssao.frag +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D texturePositionDepth : register(t0); -SamplerState samplerPositionDepth : register(s0); -Texture2D textureNormal : register(t1); -SamplerState samplerNormal : register(s1); -Texture2D ssaoNoiseTexture : register(t2); -SamplerState ssaoNoiseSampler : register(s2); - -#define SSAO_KERNEL_ARRAY_SIZE 64 -[[vk::constant_id(0)]] const int SSAO_KERNEL_SIZE = 64; -[[vk::constant_id(1)]] const float SSAO_RADIUS = 0.5; - -struct UBOSSAOKernel -{ - float4 samples[SSAO_KERNEL_ARRAY_SIZE]; -}; -cbuffer uboSSAOKernel : register(b3) { UBOSSAOKernel uboSSAOKernel; }; - -struct UBO -{ - float4x4 projection; -}; -cbuffer ubo : register(b4) { UBO ubo; }; - -float main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - // Get G-Buffer values - float3 fragPos = texturePositionDepth.Sample(samplerPositionDepth, inUV).rgb; - float3 normal = normalize(textureNormal.Sample(samplerNormal, inUV).rgb * 2.0 - 1.0); - - // Get a random vector using a noise lookup - int2 texDim; - texturePositionDepth.GetDimensions(texDim.x, texDim.y); - int2 noiseDim; - ssaoNoiseTexture.GetDimensions(noiseDim.x, noiseDim.y); - const float2 noiseUV = float2(float(texDim.x)/float(noiseDim.x), float(texDim.y)/(noiseDim.y)) * inUV; - float3 randomVec = ssaoNoiseTexture.Sample(ssaoNoiseSampler, noiseUV).xyz * 2.0 - 1.0; - - // Create TBN matrix - float3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); - float3 bitangent = cross(tangent, normal); - float3x3 TBN = transpose(float3x3(tangent, bitangent, normal)); - - // Calculate occlusion value - float occlusion = 0.0f; - for(int i = 0; i < SSAO_KERNEL_SIZE; i++) - { - float3 samplePos = mul(TBN, uboSSAOKernel.samples[i].xyz); - samplePos = fragPos + samplePos * SSAO_RADIUS; - - // project - float4 offset = float4(samplePos, 1.0f); - offset = mul(ubo.projection, offset); - offset.xyz /= offset.w; - offset.xyz = offset.xyz * 0.5f + 0.5f; - - float sampleDepth = -texturePositionDepth.Sample(samplerPositionDepth, offset.xy).w; - - float rangeCheck = smoothstep(0.0f, 1.0f, SSAO_RADIUS / abs(fragPos.z - sampleDepth)); - occlusion += (sampleDepth >= samplePos.z ? 1.0f : 0.0f) * rangeCheck; - } - occlusion = 1.0 - (occlusion / float(SSAO_KERNEL_SIZE)); - - return occlusion; -} - diff --git a/shaders/hlsl/ssao/ssao.frag.spv b/shaders/hlsl/ssao/ssao.frag.spv deleted file mode 100644 index f0b88c68..00000000 Binary files a/shaders/hlsl/ssao/ssao.frag.spv and /dev/null differ diff --git a/shaders/hlsl/stencilbuffer/outline.frag b/shaders/hlsl/stencilbuffer/outline.frag deleted file mode 100644 index 9892e709..00000000 --- a/shaders/hlsl/stencilbuffer/outline.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main() : SV_TARGET -{ - return float4(1.0, 1.0, 1.0, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/stencilbuffer/outline.frag.spv b/shaders/hlsl/stencilbuffer/outline.frag.spv deleted file mode 100644 index da33b821..00000000 Binary files a/shaders/hlsl/stencilbuffer/outline.frag.spv and /dev/null differ diff --git a/shaders/hlsl/stencilbuffer/outline.vert b/shaders/hlsl/stencilbuffer/outline.vert deleted file mode 100644 index 7f1f17a7..00000000 --- a/shaders/hlsl/stencilbuffer/outline.vert +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(2)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; - float outlineWidth; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -float4 main(VSInput input) : SV_POSITION -{ - // Extrude along normal - float4 pos = float4(input.Pos.xyz + input.Normal * ubo.outlineWidth, input.Pos.w); - return mul(ubo.projection, mul(ubo.model, pos)); -} diff --git a/shaders/hlsl/stencilbuffer/outline.vert.spv b/shaders/hlsl/stencilbuffer/outline.vert.spv deleted file mode 100644 index 4941da1c..00000000 Binary files a/shaders/hlsl/stencilbuffer/outline.vert.spv and /dev/null differ diff --git a/shaders/hlsl/stencilbuffer/toon.frag b/shaders/hlsl/stencilbuffer/toon.frag deleted file mode 100644 index 990105ff..00000000 --- a/shaders/hlsl/stencilbuffer/toon.frag +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 color; - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float intensity = dot(N,L); - if (intensity > 0.98) - color = input.Color * 1.5; - else if (intensity > 0.9) - color = input.Color * 1.0; - else if (intensity > 0.5) - color = input.Color * 0.6; - else if (intensity > 0.25) - color = input.Color * 0.4; - else - color = input.Color * 0.2; - // Desaturate a bit - color = lerp(color, dot(float3(0.2126,0.7152,0.0722), color).xxx, 0.1); - return float4(color, 1); -} \ No newline at end of file diff --git a/shaders/hlsl/stencilbuffer/toon.frag.spv b/shaders/hlsl/stencilbuffer/toon.frag.spv deleted file mode 100644 index bc7b2608..00000000 Binary files a/shaders/hlsl/stencilbuffer/toon.frag.spv and /dev/null differ diff --git a/shaders/hlsl/stencilbuffer/toon.vert b/shaders/hlsl/stencilbuffer/toon.vert deleted file mode 100644 index 7ab4fdfe..00000000 --- a/shaders/hlsl/stencilbuffer/toon.vert +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = float3(1.0, 0.0, 0.0); - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/stencilbuffer/toon.vert.spv b/shaders/hlsl/stencilbuffer/toon.vert.spv deleted file mode 100644 index 608fddb7..00000000 Binary files a/shaders/hlsl/stencilbuffer/toon.vert.spv and /dev/null differ diff --git a/shaders/hlsl/subpasses/composition.frag b/shaders/hlsl/subpasses/composition.frag deleted file mode 100644 index 6ded440b..00000000 --- a/shaders/hlsl/subpasses/composition.frag +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2020 Google LLC - -[[vk::input_attachment_index(0)]][[vk::binding(0)]] SubpassInput inputPosition; -[[vk::input_attachment_index(1)]][[vk::binding(1)]] SubpassInput inputNormal; -[[vk::input_attachment_index(2)]][[vk::binding(2)]] SubpassInput inputAlbedo; - -struct Light { - float4 position; - float3 color; - float radius; -}; - -RWStructuredBuffer lights: register(u3); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD) : SV_TARGET -{ - // Read G-Buffer values from previous sub pass - float3 fragPos = inputPosition.SubpassLoad().rgb; - float3 normal = inputNormal.SubpassLoad().rgb; - float4 albedo = inputAlbedo.SubpassLoad(); - - #define ambient 0.05 - - // Ambient part - float3 fragcolor = albedo.rgb * ambient; - - uint lightsLength; - uint lightsStride; - lights.GetDimensions(lightsLength, lightsStride); - - for(int i = 0; i < lightsLength; ++i) - { - float3 L = lights[i].position.xyz - fragPos; - float dist = length(L); - - L = normalize(L); - - float atten = lights[i].radius / (pow(dist, 3.0) + 1.0); - float3 N = normalize(normal); - float NdotL = max(0.0, dot(N, L)); - float3 diff = lights[i].color * albedo.rgb * NdotL * atten; - - fragcolor += diff; - } - - return float4(fragcolor, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/subpasses/composition.frag.spv b/shaders/hlsl/subpasses/composition.frag.spv deleted file mode 100644 index b0f438a9..00000000 Binary files a/shaders/hlsl/subpasses/composition.frag.spv and /dev/null differ diff --git a/shaders/hlsl/subpasses/composition.vert b/shaders/hlsl/subpasses/composition.vert deleted file mode 100644 index 188b7298..00000000 --- a/shaders/hlsl/subpasses/composition.vert +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(uint VertexIndex : SV_VertexID) -{ - VSOutput output = (VSOutput)0; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/subpasses/composition.vert.spv b/shaders/hlsl/subpasses/composition.vert.spv deleted file mode 100644 index 46c4b31f..00000000 Binary files a/shaders/hlsl/subpasses/composition.vert.spv and /dev/null differ diff --git a/shaders/hlsl/subpasses/gbuffer.frag b/shaders/hlsl/subpasses/gbuffer.frag deleted file mode 100644 index 2e278903..00000000 --- a/shaders/hlsl/subpasses/gbuffer.frag +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 WorldPos : POSITION0; -}; - -struct FSOutput -{ -[[vk::location(0)]] float4 Color : SV_TARGET0; -[[vk::location(1)]] float4 Position : SV_TARGET1; -[[vk::location(2)]] float4 Normal : SV_TARGET2; -[[vk::location(3)]] float4 Albedo : SV_TARGET3; -}; - -[[vk::constant_id(0)]] const float NEAR_PLANE = 0.1f; -[[vk::constant_id(1)]] const float FAR_PLANE = 256.0f; - -float linearDepth(float depth) -{ - float z = depth * 2.0f - 1.0f; - return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE)); -} - -FSOutput main(VSOutput input) -{ - FSOutput output = (FSOutput)0; - output.Position = float4(input.WorldPos, 1.0); - - float3 N = normalize(input.Normal); - N.y = -N.y; - output.Normal = float4(N, 1.0); - - output.Albedo.rgb = input.Color; - - // Store linearized depth in alpha component - output.Position.a = linearDepth(input.Pos.z); - - // Write color attachments to avoid undefined behaviour (validation error) - output.Color = float4(0.0, 0.0, 0.0, 0.0); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/subpasses/gbuffer.frag.spv b/shaders/hlsl/subpasses/gbuffer.frag.spv deleted file mode 100644 index ec48ef2d..00000000 Binary files a/shaders/hlsl/subpasses/gbuffer.frag.spv and /dev/null differ diff --git a/shaders/hlsl/subpasses/gbuffer.vert b/shaders/hlsl/subpasses/gbuffer.vert deleted file mode 100644 index d4f7d73e..00000000 --- a/shaders/hlsl/subpasses/gbuffer.vert +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 WorldPos : POSITION0; -[[vk::location(3)]] float3 Tangent : TEXCOORD1; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos))); - - // Vertex position in world space - output.WorldPos = mul(ubo.model, input.Pos).xyz; - // GL to Vulkan coord space - output.WorldPos.y = -output.WorldPos.y; - - // Normal in world space - output.Normal = mul((float3x3)ubo.model, normalize(input.Normal)); - - // Currently just vertex color - output.Color = input.Color; - return output; -} diff --git a/shaders/hlsl/subpasses/gbuffer.vert.spv b/shaders/hlsl/subpasses/gbuffer.vert.spv deleted file mode 100644 index 33166e7f..00000000 Binary files a/shaders/hlsl/subpasses/gbuffer.vert.spv and /dev/null differ diff --git a/shaders/hlsl/subpasses/transparent.frag b/shaders/hlsl/subpasses/transparent.frag deleted file mode 100644 index 28b46bc1..00000000 --- a/shaders/hlsl/subpasses/transparent.frag +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 Google LLC - -[[vk::input_attachment_index(0)]][[vk::binding(1)]] SubpassInput samplerPositionDepth; -Texture2D textureTexture : register(t2); -SamplerState samplerTexture : register(s2); - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -[[vk::constant_id(0)]] const float NEAR_PLANE = 0.1f; -[[vk::constant_id(1)]] const float FAR_PLANE = 256.0f; - -float linearDepth(float depth) -{ - float z = depth * 2.0f - 1.0f; - return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE)); -} - -float4 main (VSOutput input) : SV_TARGET -{ - // Sample depth from deferred depth buffer and discard if obscured - float depth = samplerPositionDepth.SubpassLoad().a; - if ((depth != 0.0) && (linearDepth(input.Pos.z) > depth)) - { - clip(-1); - }; - - return textureTexture.Sample(samplerTexture, input.UV); -} diff --git a/shaders/hlsl/subpasses/transparent.frag.spv b/shaders/hlsl/subpasses/transparent.frag.spv deleted file mode 100644 index e385546f..00000000 Binary files a/shaders/hlsl/subpasses/transparent.frag.spv and /dev/null differ diff --git a/shaders/hlsl/subpasses/transparent.vert b/shaders/hlsl/subpasses/transparent.vert deleted file mode 100644 index 4d327410..00000000 --- a/shaders/hlsl/subpasses/transparent.vert +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -VSOutput main (VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.UV = input.UV; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/subpasses/transparent.vert.spv b/shaders/hlsl/subpasses/transparent.vert.spv deleted file mode 100644 index fb8eee0e..00000000 Binary files a/shaders/hlsl/subpasses/transparent.vert.spv and /dev/null differ diff --git a/shaders/hlsl/terraintessellation/skysphere.frag b/shaders/hlsl/terraintessellation/skysphere.frag deleted file mode 100644 index a40c1b13..00000000 --- a/shaders/hlsl/terraintessellation/skysphere.frag +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t1); -SamplerState samplerColorMap : register(s1); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOODR0) : SV_TARGET -{ - float4 color = textureColorMap.Sample(samplerColorMap, inUV); - return float4(color.rgb, 1.0); -} diff --git a/shaders/hlsl/terraintessellation/skysphere.frag.spv b/shaders/hlsl/terraintessellation/skysphere.frag.spv deleted file mode 100644 index 824f9756..00000000 Binary files a/shaders/hlsl/terraintessellation/skysphere.frag.spv and /dev/null differ diff --git a/shaders/hlsl/terraintessellation/skysphere.vert b/shaders/hlsl/terraintessellation/skysphere.vert deleted file mode 100644 index 3b7151ff..00000000 --- a/shaders/hlsl/terraintessellation/skysphere.vert +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 mvp; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = mul(ubo.mvp, float4(input.Pos, 1.0)); - output.UV = input.UV; - return output; -} diff --git a/shaders/hlsl/terraintessellation/skysphere.vert.spv b/shaders/hlsl/terraintessellation/skysphere.vert.spv deleted file mode 100644 index 0ea62408..00000000 Binary files a/shaders/hlsl/terraintessellation/skysphere.vert.spv and /dev/null differ diff --git a/shaders/hlsl/terraintessellation/terrain.frag b/shaders/hlsl/terraintessellation/terrain.frag deleted file mode 100644 index ee1a2991..00000000 --- a/shaders/hlsl/terraintessellation/terrain.frag +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureHeight : register(t1); -SamplerState samplerHeight : register(s1); -Texture2DArray textureLayers : register(t2); -SamplerState samplerLayers : register(s2); - -struct DSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -[[vk::location(4)]] float3 EyePos : POSITION1; -[[vk::location(5)]] float3 WorldPos : POSITION0; -}; - -float3 sampleTerrainLayer(float2 inUV) -{ - // Define some layer ranges for sampling depending on terrain height - float2 layers[6]; - layers[0] = float2(-10.0, 10.0); - layers[1] = float2(5.0, 45.0); - layers[2] = float2(45.0, 80.0); - layers[3] = float2(75.0, 100.0); - layers[4] = float2(95.0, 140.0); - layers[5] = float2(140.0, 190.0); - - float3 color = float3(0.0, 0.0, 0.0); - - // Get height from displacement map - float height = textureHeight.SampleLevel(samplerHeight, inUV, 0.0).r * 255.0; - - for (int i = 0; i < 6; i++) - { - float range = layers[i].y - layers[i].x; - float weight = (range - abs(height - layers[i].y)) / range; - weight = max(0.0, weight); - color += weight * textureLayers.Sample(samplerLayers, float3(inUV * 16.0, i)).rgb; - } - - return color; -} - -float fog(float density, float4 FragCoord) -{ - const float LOG2 = -1.442695; - float dist = FragCoord.z / FragCoord.w * 0.1; - float d = density * dist; - return 1.0 - clamp(exp2(d * d * LOG2), 0.0, 1.0); -} - -float4 main(DSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 ambient = float3(0.5, 0.5, 0.5); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - - float4 color = float4((ambient + diffuse) * sampleTerrainLayer(input.UV), 1.0); - - const float4 fogColor = float4(0.47, 0.5, 0.67, 0.0); - return lerp(color, fogColor, fog(0.25, input.Pos)); -} diff --git a/shaders/hlsl/terraintessellation/terrain.frag.spv b/shaders/hlsl/terraintessellation/terrain.frag.spv deleted file mode 100644 index f6fc2f2a..00000000 Binary files a/shaders/hlsl/terraintessellation/terrain.frag.spv and /dev/null differ diff --git a/shaders/hlsl/terraintessellation/terrain.tesc b/shaders/hlsl/terraintessellation/terrain.tesc deleted file mode 100644 index 595546f5..00000000 --- a/shaders/hlsl/terraintessellation/terrain.tesc +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2020 Google LLC - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; - float4 frustumPlanes[6]; - float displacementFactor; - float tessellationFactor; - float2 viewportDim; - float tessellatedEdgeSize; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -Texture2D textureHeight : register(t1); -SamplerState samplerHeight : register(s1); - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct HSOutput -{ -[[vk::location(2)]] float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[4] : SV_TessFactor; - float TessLevelInner[2] : SV_InsideTessFactor; -}; - -// Calculate the tessellation factor based on screen space -// dimensions of the edge -float screenSpaceTessFactor(float4 p0, float4 p1) -{ - // Calculate edge mid point - float4 midPoint = 0.5 * (p0 + p1); - // Sphere radius as distance between the control points - float radius = distance(p0, p1) / 2.0; - - // View space - float4 v0 = mul(ubo.modelview, midPoint); - - // Project into clip space - float4 clip0 = mul(ubo.projection, (v0 - float4(radius, float3(0.0, 0.0, 0.0)))); - float4 clip1 = mul(ubo.projection, (v0 + float4(radius, float3(0.0, 0.0, 0.0)))); - - // Get normalized device coordinates - clip0 /= clip0.w; - clip1 /= clip1.w; - - // Convert to viewport coordinates - clip0.xy *= ubo.viewportDim; - clip1.xy *= ubo.viewportDim; - - // Return the tessellation factor based on the screen size - // given by the distance of the two edge control points in screen space - // and a reference (min.) tessellation size for the edge set by the application - return clamp(distance(clip0, clip1) / ubo.tessellatedEdgeSize * ubo.tessellationFactor, 1.0, 64.0); -} - -// Checks the current's patch visibility against the frustum using a sphere check -// Sphere radius is given by the patch size -bool frustumCheck(float4 Pos, float2 inUV) -{ - // Fixed radius (increase if patch size is increased in example) - const float radius = 8.0f; - float4 pos = Pos; - pos.y -= textureHeight.SampleLevel(samplerHeight, inUV, 0.0).r * ubo.displacementFactor; - - // Check sphere against frustum planes - for (int i = 0; i < 6; i++) { - if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0) - { - return false; - } - } - return true; -} - -ConstantsHSOutput ConstantsHS(InputPatch patch) -{ - ConstantsHSOutput output = (ConstantsHSOutput)0; - - if (!frustumCheck(patch[0].Pos, patch[0].UV)) - { - output.TessLevelInner[0] = 0.0; - output.TessLevelInner[1] = 0.0; - output.TessLevelOuter[0] = 0.0; - output.TessLevelOuter[1] = 0.0; - output.TessLevelOuter[2] = 0.0; - output.TessLevelOuter[3] = 0.0; - } - else - { - if (ubo.tessellationFactor > 0.0) - { - output.TessLevelOuter[0] = screenSpaceTessFactor(patch[3].Pos, patch[0].Pos); - output.TessLevelOuter[1] = screenSpaceTessFactor(patch[0].Pos, patch[1].Pos); - output.TessLevelOuter[2] = screenSpaceTessFactor(patch[1].Pos, patch[2].Pos); - output.TessLevelOuter[3] = screenSpaceTessFactor(patch[2].Pos, patch[3].Pos); - output.TessLevelInner[0] = lerp(output.TessLevelOuter[0], output.TessLevelOuter[3], 0.5); - output.TessLevelInner[1] = lerp(output.TessLevelOuter[2], output.TessLevelOuter[1], 0.5); - } - else - { - // Tessellation factor can be set to zero by example - // to demonstrate a simple passthrough - output.TessLevelInner[0] = 1.0; - output.TessLevelInner[1] = 1.0; - output.TessLevelOuter[0] = 1.0; - output.TessLevelOuter[1] = 1.0; - output.TessLevelOuter[2] = 1.0; - output.TessLevelOuter[3] = 1.0; - } - } - - return output; -} - -[domain("quad")] -[partitioning("integer")] -[outputtopology("triangle_cw")] -[outputcontrolpoints(4)] -[patchconstantfunc("ConstantsHS")] -[maxtessfactor(20.0f)] -HSOutput main(InputPatch patch, uint InvocationID : SV_OutputControlPointID) -{ - HSOutput output = (HSOutput)0; - output.Pos = patch[InvocationID].Pos; - output.Normal = patch[InvocationID].Normal; - output.UV = patch[InvocationID].UV; - return output; -} diff --git a/shaders/hlsl/terraintessellation/terrain.tesc.spv b/shaders/hlsl/terraintessellation/terrain.tesc.spv deleted file mode 100644 index 676d3259..00000000 Binary files a/shaders/hlsl/terraintessellation/terrain.tesc.spv and /dev/null differ diff --git a/shaders/hlsl/terraintessellation/terrain.tese b/shaders/hlsl/terraintessellation/terrain.tese deleted file mode 100644 index c9646108..00000000 --- a/shaders/hlsl/terraintessellation/terrain.tese +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2020 Google LLC - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; - float4 frustumPlanes[6]; - float displacementFactor; - float tessellationFactor; - float2 viewportDim; - float tessellatedEdgeSize; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -Texture2D displacementMapTexture : register(t1); -SamplerState displacementMapSampler : register(s1); - -struct HSOutput -{ -[[vk::location(2)]] float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[4] : SV_TessFactor; - float TessLevelInner[2] : SV_InsideTessFactor; -}; - -struct DSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -[[vk::location(4)]] float3 EyePos : POSITION1; -[[vk::location(5)]] float3 WorldPos : POSITION0; -}; - -[domain("quad")] -DSOutput main(ConstantsHSOutput input, float2 TessCoord : SV_DomainLocation, const OutputPatch patch) -{ - // Interpolate UV coordinates - DSOutput output = (DSOutput)0; - float2 uv1 = lerp(patch[0].UV, patch[1].UV, TessCoord.x); - float2 uv2 = lerp(patch[3].UV, patch[2].UV, TessCoord.x); - output.UV = lerp(uv1, uv2, TessCoord.y); - - float3 n1 = lerp(patch[0].Normal, patch[1].Normal, TessCoord.x); - float3 n2 = lerp(patch[3].Normal, patch[2].Normal, TessCoord.x); - output.Normal = lerp(n1, n2, TessCoord.y); - - // Interpolate positions - float4 pos1 = lerp(patch[0].Pos, patch[1].Pos, TessCoord.x); - float4 pos2 = lerp(patch[3].Pos, patch[2].Pos, TessCoord.x); - float4 pos = lerp(pos1, pos2, TessCoord.y); - // Displace - pos.y -= displacementMapTexture.SampleLevel(displacementMapSampler, output.UV, 0.0).r * ubo.displacementFactor; - // Perspective projection - output.Pos = mul(ubo.projection, mul(ubo.modelview, pos)); - - // Calculate vectors for lighting based on tessellated position - output.ViewVec = -pos.xyz; - output.LightVec = normalize(ubo.lightPos.xyz + output.ViewVec); - output.WorldPos = pos.xyz; - output.EyePos = mul(ubo.modelview, pos).xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/terraintessellation/terrain.tese.spv b/shaders/hlsl/terraintessellation/terrain.tese.spv deleted file mode 100644 index fc0840dc..00000000 Binary files a/shaders/hlsl/terraintessellation/terrain.tese.spv and /dev/null differ diff --git a/shaders/hlsl/terraintessellation/terrain.vert b/shaders/hlsl/terraintessellation/terrain.vert deleted file mode 100644 index 06898dfe..00000000 --- a/shaders/hlsl/terraintessellation/terrain.vert +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = float4(input.Pos.xyz, 1.0); - output.UV = input.UV; - output.Normal = input.Normal; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/terraintessellation/terrain.vert.spv b/shaders/hlsl/terraintessellation/terrain.vert.spv deleted file mode 100644 index d3f97743..00000000 Binary files a/shaders/hlsl/terraintessellation/terrain.vert.spv and /dev/null differ diff --git a/shaders/hlsl/tessellation/base.frag b/shaders/hlsl/tessellation/base.frag deleted file mode 100644 index 0d7787e5..00000000 --- a/shaders/hlsl/tessellation/base.frag +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColorMap : register(t0, space1); -SamplerState samplerColorMap : register(s0, space1); - -struct DSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -float4 main(DSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(float3(0.0, -4.0, 4.0)); - - float4 color = textureColorMap.Sample(samplerColorMap, input.UV); - - return float4(clamp(max(dot(N,L), 0.0), 0.2, 1.0) * color.rgb * 1.5, 1); -} diff --git a/shaders/hlsl/tessellation/base.frag.spv b/shaders/hlsl/tessellation/base.frag.spv deleted file mode 100644 index b055c461..00000000 Binary files a/shaders/hlsl/tessellation/base.frag.spv and /dev/null differ diff --git a/shaders/hlsl/tessellation/base.vert b/shaders/hlsl/tessellation/base.vert deleted file mode 100644 index 3fcb8aec..00000000 --- a/shaders/hlsl/tessellation/base.vert +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = float4(input.Pos.xyz, 1.0); - output.Normal = input.Normal; - output.UV = input.UV; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/tessellation/base.vert.spv b/shaders/hlsl/tessellation/base.vert.spv deleted file mode 100644 index 86de6853..00000000 Binary files a/shaders/hlsl/tessellation/base.vert.spv and /dev/null differ diff --git a/shaders/hlsl/tessellation/passthrough.tesc b/shaders/hlsl/tessellation/passthrough.tesc deleted file mode 100644 index 738b2229..00000000 --- a/shaders/hlsl/tessellation/passthrough.tesc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct HSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner : SV_InsideTessFactor; -}; - -ConstantsHSOutput ConstantsHS(InputPatch patch, uint InvocationID : SV_PrimitiveID) -{ - ConstantsHSOutput output = (ConstantsHSOutput)0; - output.TessLevelInner = 1; - output.TessLevelOuter[0] = 1; - output.TessLevelOuter[1] = 1; - output.TessLevelOuter[2] = 1; - return output; -} - -[domain("tri")] -[partitioning("integer")] -[outputtopology("triangle_ccw")] -[outputcontrolpoints(3)] -[patchconstantfunc("ConstantsHS")] -[maxtessfactor(20.0f)] -HSOutput main(InputPatch patch, uint InvocationID : SV_OutputControlPointID) -{ - HSOutput output = (HSOutput)0; - output.Pos = patch[InvocationID].Pos; - output.Normal = patch[InvocationID].Normal; - output.UV = patch[InvocationID].UV; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/tessellation/passthrough.tesc.spv b/shaders/hlsl/tessellation/passthrough.tesc.spv deleted file mode 100644 index 8eac1702..00000000 Binary files a/shaders/hlsl/tessellation/passthrough.tesc.spv and /dev/null differ diff --git a/shaders/hlsl/tessellation/passthrough.tese b/shaders/hlsl/tessellation/passthrough.tese deleted file mode 100644 index 1c23d91b..00000000 --- a/shaders/hlsl/tessellation/passthrough.tese +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Google LLC - -struct UBO -{ - float4x4 projection; - float4x4 model; - float tessAlpha; - float tessLevel; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct HSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner : SV_InsideTessFactor; -}; - -struct DSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -[domain("tri")] -DSOutput main(ConstantsHSOutput input, float3 TessCoord : SV_DomainLocation, const OutputPatch patch) -{ - DSOutput output = (DSOutput)0; - output.Pos = (TessCoord.x * patch[0].Pos) + - (TessCoord.y * patch[1].Pos) + - (TessCoord.z * patch[2].Pos); - output.Pos = mul(ubo.projection, mul(ubo.model, output.Pos)); - - output.Normal = TessCoord.x*patch[0].Normal + TessCoord.y*patch[1].Normal + TessCoord.z*patch[2].Normal; - output.UV = TessCoord.x*patch[0].UV + TessCoord.y*patch[1].UV + TessCoord.z*patch[2].UV; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/tessellation/passthrough.tese.spv b/shaders/hlsl/tessellation/passthrough.tese.spv deleted file mode 100644 index 97493633..00000000 Binary files a/shaders/hlsl/tessellation/passthrough.tese.spv and /dev/null differ diff --git a/shaders/hlsl/tessellation/pntriangles.tesc b/shaders/hlsl/tessellation/pntriangles.tesc deleted file mode 100644 index b85bb7ef..00000000 --- a/shaders/hlsl/tessellation/pntriangles.tesc +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2020 Google LLC - -// PN patch data -struct PnPatch -{ - float b210; - float b120; - float b021; - float b012; - float b102; - float b201; - float b111; - float n110; - float n011; - float n101; -}; - -// tessellation levels -struct UBO -{ - float4x4 projection; - float4x4 model; - float tessAlpha; - float tessLevel; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct HSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float2 UV : TEXCOORD0; -[[vk::location(6)]] float pnPatch[10] : TEXCOORD6; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner : SV_InsideTessFactor; -}; - -void SetPnPatch(out float output[10], PnPatch patch) -{ - output[0] = patch.b210; - output[1] = patch.b120; - output[2] = patch.b021; - output[3] = patch.b012; - output[4] = patch.b102; - output[5] = patch.b201; - output[6] = patch.b111; - output[7] = patch.n110; - output[8] = patch.n011; - output[9] = patch.n101; -} - -float wij(float4 iPos, float3 iNormal, float4 jPos) -{ - return dot(jPos.xyz - iPos.xyz, iNormal); -} - -float vij(float4 iPos, float3 iNormal, float4 jPos, float3 jNormal) -{ - float3 Pj_minus_Pi = jPos.xyz - - iPos.xyz; - float3 Ni_plus_Nj = iNormal+jNormal; - return 2.0*dot(Pj_minus_Pi, Ni_plus_Nj)/dot(Pj_minus_Pi, Pj_minus_Pi); -} - -ConstantsHSOutput ConstantsHS(InputPatch patch, uint InvocationID : SV_PrimitiveID) -{ - ConstantsHSOutput output = (ConstantsHSOutput)0; - output.TessLevelOuter[0] = ubo.tessLevel; - output.TessLevelOuter[1] = ubo.tessLevel; - output.TessLevelOuter[2] = ubo.tessLevel; - output.TessLevelInner = ubo.tessLevel; - return output; -} - -[domain("tri")] -[partitioning("fractional_odd")] -[outputtopology("triangle_cw")] -[outputcontrolpoints(3)] -[patchconstantfunc("ConstantsHS")] -[maxtessfactor(20.0f)] -HSOutput main(InputPatch patch, uint InvocationID : SV_OutputControlPointID) -{ - HSOutput output = (HSOutput)0; - // get data - output.Pos = patch[InvocationID].Pos; - output.Normal = patch[InvocationID].Normal; - output.UV = patch[InvocationID].UV; - - // set base - float P0 = patch[0].Pos[InvocationID]; - float P1 = patch[1].Pos[InvocationID]; - float P2 = patch[2].Pos[InvocationID]; - float N0 = patch[0].Normal[InvocationID]; - float N1 = patch[1].Normal[InvocationID]; - float N2 = patch[2].Normal[InvocationID]; - - // compute control points - PnPatch pnPatch; - pnPatch.b210 = (2.0*P0 + P1 - wij(patch[0].Pos, patch[0].Normal, patch[1].Pos)*N0)/3.0; - pnPatch.b120 = (2.0*P1 + P0 - wij(patch[1].Pos, patch[1].Normal, patch[0].Pos)*N1)/3.0; - pnPatch.b021 = (2.0*P1 + P2 - wij(patch[1].Pos, patch[1].Normal, patch[2].Pos)*N1)/3.0; - pnPatch.b012 = (2.0*P2 + P1 - wij(patch[2].Pos, patch[2].Normal, patch[1].Pos)*N2)/3.0; - pnPatch.b102 = (2.0*P2 + P0 - wij(patch[2].Pos, patch[2].Normal, patch[0].Pos)*N2)/3.0; - pnPatch.b201 = (2.0*P0 + P2 - wij(patch[0].Pos, patch[0].Normal, patch[2].Pos)*N0)/3.0; - float E = ( pnPatch.b210 - + pnPatch.b120 - + pnPatch.b021 - + pnPatch.b012 - + pnPatch.b102 - + pnPatch.b201 ) / 6.0; - float V = (P0 + P1 + P2)/3.0; - pnPatch.b111 = E + (E - V)*0.5; - pnPatch.n110 = N0+N1-vij(patch[0].Pos, patch[0].Normal, patch[1].Pos, patch[1].Normal)*(P1-P0); - pnPatch.n011 = N1+N2-vij(patch[1].Pos, patch[1].Normal, patch[2].Pos, patch[2].Normal)*(P2-P1); - pnPatch.n101 = N2+N0-vij(patch[2].Pos, patch[2].Normal, patch[0].Pos, patch[0].Normal)*(P0-P2); - SetPnPatch(output.pnPatch, pnPatch); - - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/tessellation/pntriangles.tesc.spv b/shaders/hlsl/tessellation/pntriangles.tesc.spv deleted file mode 100644 index 1a8ab8f4..00000000 Binary files a/shaders/hlsl/tessellation/pntriangles.tesc.spv and /dev/null differ diff --git a/shaders/hlsl/tessellation/pntriangles.tese b/shaders/hlsl/tessellation/pntriangles.tese deleted file mode 100644 index ea72be4d..00000000 --- a/shaders/hlsl/tessellation/pntriangles.tese +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2020 Google LLC - -// PN patch data -struct PnPatch -{ - float b210; - float b120; - float b021; - float b012; - float b102; - float b201; - float b111; - float n110; - float n011; - float n101; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float tessAlpha; - float tessLevel; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct HSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float2 UV : TEXCOORD0; -[[vk::location(6)]] float pnPatch[10] : TEXCOORD6; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner : SV_InsideTessFactor; -}; - -struct DSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -#define uvw TessCoord - -PnPatch GetPnPatch(float pnPatch[10]) -{ - PnPatch output; - output.b210 = pnPatch[0]; - output.b120 = pnPatch[1]; - output.b021 = pnPatch[2]; - output.b012 = pnPatch[3]; - output.b102 = pnPatch[4]; - output.b201 = pnPatch[5]; - output.b111 = pnPatch[6]; - output.n110 = pnPatch[7]; - output.n011 = pnPatch[8]; - output.n101 = pnPatch[9]; - return output; -} - -[domain("tri")] -DSOutput main(ConstantsHSOutput input, float3 TessCoord : SV_DomainLocation, const OutputPatch patch) -{ - PnPatch pnPatch[3]; - pnPatch[0] = GetPnPatch(patch[0].pnPatch); - pnPatch[1] = GetPnPatch(patch[1].pnPatch); - pnPatch[2] = GetPnPatch(patch[2].pnPatch); - - DSOutput output = (DSOutput)0; - float3 uvwSquared = uvw * uvw; - float3 uvwCubed = uvwSquared * uvw; - - // extract control points - float3 b210 = float3(pnPatch[0].b210, pnPatch[1].b210, pnPatch[2].b210); - float3 b120 = float3(pnPatch[0].b120, pnPatch[1].b120, pnPatch[2].b120); - float3 b021 = float3(pnPatch[0].b021, pnPatch[1].b021, pnPatch[2].b021); - float3 b012 = float3(pnPatch[0].b012, pnPatch[1].b012, pnPatch[2].b012); - float3 b102 = float3(pnPatch[0].b102, pnPatch[1].b102, pnPatch[2].b102); - float3 b201 = float3(pnPatch[0].b201, pnPatch[1].b201, pnPatch[2].b201); - float3 b111 = float3(pnPatch[0].b111, pnPatch[1].b111, pnPatch[2].b111); - - // extract control normals - float3 n110 = normalize(float3(pnPatch[0].n110, pnPatch[1].n110, pnPatch[2].n110)); - float3 n011 = normalize(float3(pnPatch[0].n011, pnPatch[1].n011, pnPatch[2].n011)); - float3 n101 = normalize(float3(pnPatch[0].n101, pnPatch[1].n101, pnPatch[2].n101)); - - // compute texcoords - output.UV = TessCoord[2]*patch[0].UV + TessCoord[0]*patch[1].UV + TessCoord[1]*patch[2].UV; - - // normal - // Barycentric normal - float3 barNormal = TessCoord[2]*patch[0].Normal + TessCoord[0]*patch[1].Normal + TessCoord[1]*patch[2].Normal; - float3 pnNormal = patch[0].Normal*uvwSquared[2] + patch[1].Normal*uvwSquared[0] + patch[2].Normal*uvwSquared[1] - + n110*uvw[2]*uvw[0] + n011*uvw[0]*uvw[1]+ n101*uvw[2]*uvw[1]; - output.Normal = ubo.tessAlpha*pnNormal + (1.0-ubo.tessAlpha) * barNormal; - - // compute interpolated pos - float3 barPos = TessCoord[2]*patch[0].Pos.xyz - + TessCoord[0]*patch[1].Pos.xyz - + TessCoord[1]*patch[2].Pos.xyz; - - // save some computations - uvwSquared *= 3.0; - - // compute PN position - float3 pnPos = patch[0].Pos.xyz*uvwCubed[2] - + patch[1].Pos.xyz*uvwCubed[0] - + patch[2].Pos.xyz*uvwCubed[1] - + b210*uvwSquared[2]*uvw[0] - + b120*uvwSquared[0]*uvw[2] - + b201*uvwSquared[2]*uvw[1] - + b021*uvwSquared[0]*uvw[1] - + b102*uvwSquared[1]*uvw[2] - + b012*uvwSquared[1]*uvw[0] - + b111*6.0*uvw[0]*uvw[1]*uvw[2]; - - // final position and normal - float3 finalPos = (1.0-ubo.tessAlpha)*barPos + ubo.tessAlpha*pnPos; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(finalPos,1.0))); - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/tessellation/pntriangles.tese.spv b/shaders/hlsl/tessellation/pntriangles.tese.spv deleted file mode 100644 index 95a1f6a8..00000000 Binary files a/shaders/hlsl/tessellation/pntriangles.tese.spv and /dev/null differ diff --git a/shaders/hlsl/textoverlay/mesh.frag b/shaders/hlsl/textoverlay/mesh.frag deleted file mode 100644 index f2eb9b6f..00000000 --- a/shaders/hlsl/textoverlay/mesh.frag +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float diffuse = max(dot(N, L), 0.0); - float specular = pow(max(dot(R, V), 0.0), 1.0); - return float4(((diffuse + specular) * 0.25).xxx, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/textoverlay/mesh.frag.spv b/shaders/hlsl/textoverlay/mesh.frag.spv deleted file mode 100644 index 6e2c26af..00000000 Binary files a/shaders/hlsl/textoverlay/mesh.frag.spv and /dev/null differ diff --git a/shaders/hlsl/textoverlay/mesh.vert b/shaders/hlsl/textoverlay/mesh.vert deleted file mode 100644 index 2abf875a..00000000 --- a/shaders/hlsl/textoverlay/mesh.vert +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, normalize(input.Normal)); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/textoverlay/mesh.vert.spv b/shaders/hlsl/textoverlay/mesh.vert.spv deleted file mode 100644 index 8430788d..00000000 Binary files a/shaders/hlsl/textoverlay/mesh.vert.spv and /dev/null differ diff --git a/shaders/hlsl/textoverlay/text.frag b/shaders/hlsl/textoverlay/text.frag deleted file mode 100644 index 7525bd19..00000000 --- a/shaders/hlsl/textoverlay/text.frag +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureFont : register(t0); -SamplerState samplerFont : register(s0); - -float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET -{ - float color = textureFont.Sample(samplerFont, inUV).r; - return color.xxxx; -} diff --git a/shaders/hlsl/textoverlay/text.frag.spv b/shaders/hlsl/textoverlay/text.frag.spv deleted file mode 100644 index eb9d3231..00000000 Binary files a/shaders/hlsl/textoverlay/text.frag.spv and /dev/null differ diff --git a/shaders/hlsl/textoverlay/text.vert b/shaders/hlsl/textoverlay/text.vert deleted file mode 100644 index 5de88481..00000000 --- a/shaders/hlsl/textoverlay/text.vert +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float2 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = float4(input.Pos, 0.0, 1.0); - output.UV = input.UV; - return output; -} diff --git a/shaders/hlsl/textoverlay/text.vert.spv b/shaders/hlsl/textoverlay/text.vert.spv deleted file mode 100644 index 4870eb42..00000000 Binary files a/shaders/hlsl/textoverlay/text.vert.spv and /dev/null differ diff --git a/shaders/hlsl/texture/texture.frag b/shaders/hlsl/texture/texture.frag deleted file mode 100644 index 78ce0f93..00000000 --- a/shaders/hlsl/texture/texture.frag +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float LodBias : TEXCOORD3; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureColor.SampleLevel(samplerColor, input.UV, input.LodBias); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a; - - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/texture/texture.frag.spv b/shaders/hlsl/texture/texture.frag.spv deleted file mode 100644 index 83be30a4..00000000 Binary files a/shaders/hlsl/texture/texture.frag.spv and /dev/null differ diff --git a/shaders/hlsl/texture/texture.vert b/shaders/hlsl/texture/texture.vert deleted file mode 100644 index 133d53b1..00000000 --- a/shaders/hlsl/texture/texture.vert +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 viewPos; - float lodBias; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float LodBias : TEXCOORD3; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - output.LodBias = ubo.lodBias; - - float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lightPos = float3(0.0, 0.0, 0.0); - float3 lPos = mul((float3x3)ubo.model, lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} diff --git a/shaders/hlsl/texture/texture.vert.spv b/shaders/hlsl/texture/texture.vert.spv deleted file mode 100644 index 61289a7d..00000000 Binary files a/shaders/hlsl/texture/texture.vert.spv and /dev/null differ diff --git a/shaders/hlsl/texture3d/texture3d.frag b/shaders/hlsl/texture3d/texture3d.frag deleted file mode 100644 index f9375205..00000000 --- a/shaders/hlsl/texture3d/texture3d.frag +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2020 Google LLC - -Texture3D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float3 UV : TEXCOORD0; -[[vk::location(1)]] float LodBias : TEXCOORD3; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureColor.Sample(samplerColor, input.UV); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.r; - - return float4(diffuse * color.r + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/texture3d/texture3d.frag.spv b/shaders/hlsl/texture3d/texture3d.frag.spv deleted file mode 100644 index 064b49cb..00000000 Binary files a/shaders/hlsl/texture3d/texture3d.frag.spv and /dev/null differ diff --git a/shaders/hlsl/texture3d/texture3d.vert b/shaders/hlsl/texture3d/texture3d.vert deleted file mode 100644 index 39c9681c..00000000 --- a/shaders/hlsl/texture3d/texture3d.vert +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 viewPos; - float depth; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UV : TEXCOORD0; -[[vk::location(1)]] float LodBias : TEXCOORD3; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = float3(input.UV, ubo.depth); - - float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lightPos = float3(0.0, 0.0, 0.0); - float3 lPos = mul((float3x3)ubo.model, lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} diff --git a/shaders/hlsl/texture3d/texture3d.vert.spv b/shaders/hlsl/texture3d/texture3d.vert.spv deleted file mode 100644 index b9f084ee..00000000 Binary files a/shaders/hlsl/texture3d/texture3d.vert.spv and /dev/null differ diff --git a/shaders/hlsl/texturearray/instancing.frag b/shaders/hlsl/texturearray/instancing.frag deleted file mode 100644 index 85ed6eae..00000000 --- a/shaders/hlsl/texturearray/instancing.frag +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2DArray textureArray : register(t1); -SamplerState samplerArray : register(s1); - -float4 main([[vk::location(0)]] float3 inUV : TEXCOORD0) : SV_TARGET -{ - return textureArray.Sample(samplerArray, inUV); -} \ No newline at end of file diff --git a/shaders/hlsl/texturearray/instancing.frag.spv b/shaders/hlsl/texturearray/instancing.frag.spv deleted file mode 100644 index 66562c25..00000000 Binary files a/shaders/hlsl/texturearray/instancing.frag.spv and /dev/null differ diff --git a/shaders/hlsl/texturearray/instancing.vert b/shaders/hlsl/texturearray/instancing.vert deleted file mode 100644 index 67670258..00000000 --- a/shaders/hlsl/texturearray/instancing.vert +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -}; - -struct Instance -{ - float4x4 model; - float arrayIndex; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - Instance instance[8]; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UV : TEXCOORD0; -}; - -VSOutput main(VSInput input, uint InstanceIndex : SV_InstanceID) -{ - VSOutput output = (VSOutput)0; - output.UV = float3(input.UV, ubo.instance[InstanceIndex].arrayIndex); - float4x4 modelView = mul(ubo.view, ubo.instance[InstanceIndex].model); - output.Pos = mul(ubo.projection, mul(modelView, float4(input.Pos, 1.0))); - return output; -} diff --git a/shaders/hlsl/texturearray/instancing.vert.spv b/shaders/hlsl/texturearray/instancing.vert.spv deleted file mode 100644 index eace2863..00000000 Binary files a/shaders/hlsl/texturearray/instancing.vert.spv and /dev/null differ diff --git a/shaders/hlsl/texturecubemap/reflect.frag b/shaders/hlsl/texturecubemap/reflect.frag deleted file mode 100644 index 7cf3efd0..00000000 --- a/shaders/hlsl/texturecubemap/reflect.frag +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureColor : register(t1); -SamplerState samplerColor : register(s1); - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 invModel; - float lodBias; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float LodBias : TEXCOORD3; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 cI = normalize (input.ViewVec); - float3 cR = reflect (cI, normalize(input.Normal)); - - cR = mul(ubo.invModel, float4(cR, 0.0)).xyz; - // Convert cubemap coordinates into Vulkan coordinate space - cR.z *= -1.0; - - float4 color = textureColor.SampleLevel(samplerColor, cR, input.LodBias); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.5, 0.5, 0.5) * color.rgb; - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.5, 0.5, 0.5); - return float4(ambient + diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/texturecubemap/reflect.frag.spv b/shaders/hlsl/texturecubemap/reflect.frag.spv deleted file mode 100644 index 02fa6b35..00000000 Binary files a/shaders/hlsl/texturecubemap/reflect.frag.spv and /dev/null differ diff --git a/shaders/hlsl/texturecubemap/reflect.vert b/shaders/hlsl/texturecubemap/reflect.vert deleted file mode 100644 index 9323ee4c..00000000 --- a/shaders/hlsl/texturecubemap/reflect.vert +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 invModel; - float lodBias; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 WorldPos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float LodBias : TEXCOORD3; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - output.WorldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.LodBias = ubo.lodBias; - - float3 lightPos = float3(0.0f, -5.0f, 5.0f); - output.LightVec = lightPos.xyz - output.WorldPos.xyz; - output.ViewVec = -output.WorldPos; - return output; -} diff --git a/shaders/hlsl/texturecubemap/reflect.vert.spv b/shaders/hlsl/texturecubemap/reflect.vert.spv deleted file mode 100644 index 85b14c35..00000000 Binary files a/shaders/hlsl/texturecubemap/reflect.vert.spv and /dev/null differ diff --git a/shaders/hlsl/texturecubemap/skybox.frag b/shaders/hlsl/texturecubemap/skybox.frag deleted file mode 100644 index bd2ba96d..00000000 --- a/shaders/hlsl/texturecubemap/skybox.frag +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureCubeMap : register(t1); -SamplerState samplerCubeMap : register(s1); - -float4 main([[vk::location(0)]] float3 inUVW : TEXCOORD0) : SV_TARGET -{ - return textureCubeMap.Sample(samplerCubeMap, inUVW); -} \ No newline at end of file diff --git a/shaders/hlsl/texturecubemap/skybox.frag.spv b/shaders/hlsl/texturecubemap/skybox.frag.spv deleted file mode 100644 index 94b27658..00000000 Binary files a/shaders/hlsl/texturecubemap/skybox.frag.spv and /dev/null differ diff --git a/shaders/hlsl/texturecubemap/skybox.vert b/shaders/hlsl/texturecubemap/skybox.vert deleted file mode 100644 index 4395feb4..00000000 --- a/shaders/hlsl/texturecubemap/skybox.vert +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 Google LLC - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UVW : TEXCOORD0; -}; - -VSOutput main([[vk::location(0)]] float3 Pos : POSITION0) -{ - VSOutput output = (VSOutput)0; - output.UVW = Pos; - // Convert cubemap coordinates into Vulkan coordinate space - output.UVW.xy *= -1.0; - // Remove translation from view matrix - float4x4 viewMat = ubo.model; - viewMat[0][3] = 0.0; - viewMat[1][3] = 0.0; - viewMat[2][3] = 0.0; - output.Pos = mul(ubo.projection, mul(viewMat, float4(Pos.xyz, 1.0))); - return output; -} diff --git a/shaders/hlsl/texturecubemap/skybox.vert.spv b/shaders/hlsl/texturecubemap/skybox.vert.spv deleted file mode 100644 index 94b7c48d..00000000 Binary files a/shaders/hlsl/texturecubemap/skybox.vert.spv and /dev/null differ diff --git a/shaders/hlsl/texturecubemaparray/reflect.frag b/shaders/hlsl/texturecubemaparray/reflect.frag deleted file mode 100644 index 4fe024c9..00000000 --- a/shaders/hlsl/texturecubemaparray/reflect.frag +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCubeArray textureCubeMapArray : register(t1); -SamplerState samplerCubeMapArray : register(s1); - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 invModel; - float lodBias; - int cubeMapIndex; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float LodBias : TEXCOORD3; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 cI = normalize (input.Pos); - float3 cR = reflect (cI, normalize(input.Normal)); - - cR = mul(ubo.invModel, float4(cR, 0.0)).xyz; - cR *= float3(1.0, -1.0, -1.0); - - float4 color = textureCubeMapArray.SampleLevel(samplerCubeMapArray, float4(cR, ubo.cubeMapIndex), input.LodBias); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.5, 0.5, 0.5) * color.rgb; - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.5, 0.5, 0.5); - return float4(ambient + diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/texturecubemaparray/reflect.frag.spv b/shaders/hlsl/texturecubemaparray/reflect.frag.spv deleted file mode 100644 index 11ae34e1..00000000 Binary files a/shaders/hlsl/texturecubemaparray/reflect.frag.spv and /dev/null differ diff --git a/shaders/hlsl/texturecubemaparray/reflect.vert b/shaders/hlsl/texturecubemaparray/reflect.vert deleted file mode 100644 index 9323ee4c..00000000 --- a/shaders/hlsl/texturecubemaparray/reflect.vert +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 invModel; - float lodBias; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 WorldPos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float LodBias : TEXCOORD3; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - output.WorldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.LodBias = ubo.lodBias; - - float3 lightPos = float3(0.0f, -5.0f, 5.0f); - output.LightVec = lightPos.xyz - output.WorldPos.xyz; - output.ViewVec = -output.WorldPos; - return output; -} diff --git a/shaders/hlsl/texturecubemaparray/reflect.vert.spv b/shaders/hlsl/texturecubemaparray/reflect.vert.spv deleted file mode 100644 index 85b14c35..00000000 Binary files a/shaders/hlsl/texturecubemaparray/reflect.vert.spv and /dev/null differ diff --git a/shaders/hlsl/texturecubemaparray/skybox.frag b/shaders/hlsl/texturecubemaparray/skybox.frag deleted file mode 100644 index 10807de6..00000000 --- a/shaders/hlsl/texturecubemaparray/skybox.frag +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCubeArray textureCubeMapArray : register(t1); -SamplerState samplerCubeMapArray : register(s1); - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 invModel; - float lodBias; - int cubeMapIndex; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -float4 main([[vk::location(0)]] float3 inUVW : TEXCOORD0) : SV_TARGET -{ - return textureCubeMapArray.SampleLevel(samplerCubeMapArray, float4(inUVW, ubo.cubeMapIndex), ubo.lodBias); -} \ No newline at end of file diff --git a/shaders/hlsl/texturecubemaparray/skybox.frag.spv b/shaders/hlsl/texturecubemaparray/skybox.frag.spv deleted file mode 100644 index 111db475..00000000 Binary files a/shaders/hlsl/texturecubemaparray/skybox.frag.spv and /dev/null differ diff --git a/shaders/hlsl/texturecubemaparray/skybox.vert b/shaders/hlsl/texturecubemaparray/skybox.vert deleted file mode 100644 index 28f7296e..00000000 --- a/shaders/hlsl/texturecubemaparray/skybox.vert +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2020 Google LLC - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 invModel; - float lodBias; - int cubeMapIndex; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UVW : TEXCOORD0; -}; - -VSOutput main([[vk::location(0)]] float3 Pos : POSITION0) -{ - VSOutput output = (VSOutput)0; - output.UVW = Pos; - output.UVW.xy *= -1.0; - // Remove translation from view matrix - float4x4 viewMat = ubo.model; - viewMat[0][3] = 0.0; - viewMat[1][3] = 0.0; - viewMat[2][3] = 0.0; - output.Pos = mul(ubo.projection, mul(viewMat, float4(Pos.xyz, 1.0))); - return output; -} diff --git a/shaders/hlsl/texturecubemaparray/skybox.vert.spv b/shaders/hlsl/texturecubemaparray/skybox.vert.spv deleted file mode 100644 index bd056977..00000000 Binary files a/shaders/hlsl/texturecubemaparray/skybox.vert.spv and /dev/null differ diff --git a/shaders/hlsl/texturemipmapgen/texture.frag b/shaders/hlsl/texturemipmapgen/texture.frag deleted file mode 100644 index b14d63d1..00000000 --- a/shaders/hlsl/texturemipmapgen/texture.frag +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplers[3] : register(s2); - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 viewPos; - float lodBias; - int samplerIndex; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float LodBias : TEXCOORD3; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = textureColor.Sample(samplers[ubo.samplerIndex], input.UV, int2(0, 0), input.LodBias); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(L, N); - float3 diffuse = max(dot(N, L), 0.65) * float3(1.0, 1.0, 1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a; - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/texturemipmapgen/texture.frag.spv b/shaders/hlsl/texturemipmapgen/texture.frag.spv deleted file mode 100644 index 838dd550..00000000 Binary files a/shaders/hlsl/texturemipmapgen/texture.frag.spv and /dev/null differ diff --git a/shaders/hlsl/texturemipmapgen/texture.vert b/shaders/hlsl/texturemipmapgen/texture.vert deleted file mode 100644 index 6bcd982d..00000000 --- a/shaders/hlsl/texturemipmapgen/texture.vert +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; -[[vk::location(2)]] float3 Normal : NORMAL0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 viewPos; - float lodBias; - int samplerIndex; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float LodBias : TEXCOORD3; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV * float2(2.0, 1.0); - output.LodBias = ubo.lodBias; - - float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lightPos = float3(-30.0, 0.0, 0.0); - output.LightVec = worldPos - lightPos; - output.ViewVec = ubo.viewPos.xyz - worldPos; - return output; -} diff --git a/shaders/hlsl/texturemipmapgen/texture.vert.spv b/shaders/hlsl/texturemipmapgen/texture.vert.spv deleted file mode 100644 index cbfc816b..00000000 Binary files a/shaders/hlsl/texturemipmapgen/texture.vert.spv and /dev/null differ diff --git a/shaders/hlsl/texturesparseresidency/sparseresidency.frag b/shaders/hlsl/texturesparseresidency/sparseresidency.frag deleted file mode 100644 index 27458545..00000000 --- a/shaders/hlsl/texturesparseresidency/sparseresidency.frag +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D textureColor : register(t1); -SamplerState samplerColor : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float LodBias : TEXCOORD3; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float4 color = float4(0.0, 0.0, 0.0, 0.0); - - // Fetch sparse until we get a valid texel - uint status; - float minLod = input.LodBias; - do - { - color = textureColor.SampleLevel(samplerColor, input.UV, minLod, 0, status); - minLod += 1.0f; - } while(!CheckAccessFullyMapped(status)); - - float3 N = normalize(input.Normal); - - N = normalize((input.Normal - 0.5) * 2.0); - - float3 L = normalize(input.LightVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.25) * color.rgb; - return float4(diffuse, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/texturesparseresidency/sparseresidency.frag.spv b/shaders/hlsl/texturesparseresidency/sparseresidency.frag.spv deleted file mode 100644 index 4249b2a2..00000000 Binary files a/shaders/hlsl/texturesparseresidency/sparseresidency.frag.spv and /dev/null differ diff --git a/shaders/hlsl/texturesparseresidency/sparseresidency.vert b/shaders/hlsl/texturesparseresidency/sparseresidency.vert deleted file mode 100644 index b5fb1236..00000000 --- a/shaders/hlsl/texturesparseresidency/sparseresidency.vert +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 viewPos; - float lodBias; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float LodBias : TEXCOORD3; -[[vk::location(2)]] float3 Normal : NORMAL0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.UV; - output.LodBias = ubo.lodBias; - output.Normal = input.Normal; - - float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float3 lightPos = float3(0.0, 50.0f, 0.0f); - output.LightVec = lightPos - input.Pos.xyz; - output.ViewVec = ubo.viewPos.xyz - worldPos.xyz; - return output; -} diff --git a/shaders/hlsl/texturesparseresidency/sparseresidency.vert.spv b/shaders/hlsl/texturesparseresidency/sparseresidency.vert.spv deleted file mode 100644 index 4a01d7cb..00000000 Binary files a/shaders/hlsl/texturesparseresidency/sparseresidency.vert.spv and /dev/null differ diff --git a/shaders/hlsl/triangle/triangle.frag b/shaders/hlsl/triangle/triangle.frag deleted file mode 100644 index 8a7faf06..00000000 --- a/shaders/hlsl/triangle/triangle.frag +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020 Google LLC - -float4 main([[vk::location(0)]] float3 Color : COLOR0) : SV_TARGET -{ - return float4(Color, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/triangle/triangle.frag.spv b/shaders/hlsl/triangle/triangle.frag.spv deleted file mode 100644 index 870fb6c1..00000000 Binary files a/shaders/hlsl/triangle/triangle.frag.spv and /dev/null differ diff --git a/shaders/hlsl/triangle/triangle.vert b/shaders/hlsl/triangle/triangle.vert deleted file mode 100644 index 881674c8..00000000 --- a/shaders/hlsl/triangle/triangle.vert +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projectionMatrix; - float4x4 modelMatrix; - float4x4 viewMatrix; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Color : COLOR0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Pos = mul(ubo.projectionMatrix, mul(ubo.viewMatrix, mul(ubo.modelMatrix, float4(input.Pos.xyz, 1.0)))); - return output; -} diff --git a/shaders/hlsl/triangle/triangle.vert.spv b/shaders/hlsl/triangle/triangle.vert.spv deleted file mode 100644 index ebd52799..00000000 Binary files a/shaders/hlsl/triangle/triangle.vert.spv and /dev/null differ diff --git a/shaders/hlsl/variablerateshading/scene.frag b/shaders/hlsl/variablerateshading/scene.frag deleted file mode 100644 index 82308994..00000000 --- a/shaders/hlsl/variablerateshading/scene.frag +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2020 Sascha Willems - -Texture2D textureColorMap : register(t0, space1); -SamplerState samplerColorMap : register(s0, space1); -Texture2D textureNormalMap : register(t1, space1); -SamplerState samplerNormalMap : register(s1, space1); - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; - float4 viewPos; - int colorShadingRates; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -[[vk::constant_id(0)]] const bool ALPHA_MASK = false; -[[vk::constant_id(1)]] const float ALPHA_MASK_CUTOFF = 0.0; - -struct VSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -[[vk::location(5)]] float4 Tangent : TEXCOORD3; -}; - -float4 main(VSOutput input, uint shadingRate : SV_ShadingRate) : SV_TARGET -{ - float4 color = textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0); - - if (ALPHA_MASK) { - if (color.a < ALPHA_MASK_CUTOFF) { - discard; - } - } - - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent.xyz); - float3 B = cross(input.Normal, input.Tangent.xyz) * input.Tangent.w; - float3x3 TBN = float3x3(T, B, N); - N = mul(normalize(textureNormalMap.Sample(samplerNormalMap, input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - - const float ambient = 0.1; - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), ambient).rrr; - float3 specular = pow(max(dot(R, V), 0.0), 32.0); - color = float4(diffuse * color.rgb + specular, color.a); - - const uint SHADING_RATE_PER_PIXEL = 0x0; - const uint SHADING_RATE_PER_2X1_PIXELS = 6; - const uint SHADING_RATE_PER_1X2_PIXELS = 7; - const uint SHADING_RATE_PER_2X2_PIXELS = 8; - const uint SHADING_RATE_PER_4X2_PIXELS = 9; - const uint SHADING_RATE_PER_2X4_PIXELS = 10; - - if (ubo.colorShadingRates == 1) { - switch(shadingRate) { - case SHADING_RATE_PER_PIXEL: - return color * float4(0.0, 0.8, 0.4, 1.0); - case SHADING_RATE_PER_2X1_PIXELS: - return color * float4(0.2, 0.6, 1.0, 1.0); - case SHADING_RATE_PER_1X2_PIXELS: - return color * float4(0.0, 0.4, 0.8, 1.0); - case SHADING_RATE_PER_2X2_PIXELS: - return color * float4(1.0, 1.0, 0.2, 1.0); - case SHADING_RATE_PER_4X2_PIXELS: - return color * float4(0.8, 0.8, 0.0, 1.0); - case SHADING_RATE_PER_2X4_PIXELS: - return color * float4(1.0, 0.4, 0.2, 1.0); - default: - return color * float4(0.8, 0.0, 0.0, 1.0); - } - } - - return color; -} \ No newline at end of file diff --git a/shaders/hlsl/variablerateshading/scene.frag.spv b/shaders/hlsl/variablerateshading/scene.frag.spv deleted file mode 100644 index d06bb483..00000000 Binary files a/shaders/hlsl/variablerateshading/scene.frag.spv and /dev/null differ diff --git a/shaders/hlsl/variablerateshading/scene.vert b/shaders/hlsl/variablerateshading/scene.vert deleted file mode 100644 index eeffc129..00000000 --- a/shaders/hlsl/variablerateshading/scene.vert +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -[[vk::location(4)]] float4 Tangent : TEXCOORD1; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; - float4 viewPos; - int colorShadingRates; -}; -cbuffer ubo : register(b0) { UBO ubo; }; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float2 UV : TEXCOORD0; -[[vk::location(3)]] float3 ViewVec : TEXCOORD1; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -[[vk::location(5)]] float4 Tangent : TEXCOORD3; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Tangent = input.Tangent; - - float4x4 modelView = mul(ubo.view, ubo.model); - - output.Pos = mul(ubo.projection, mul(modelView, float4(input.Pos.xyz, 1.0))); - - output.Normal = mul((float3x3)ubo.model, input.Normal); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} \ No newline at end of file diff --git a/shaders/hlsl/variablerateshading/scene.vert.spv b/shaders/hlsl/variablerateshading/scene.vert.spv deleted file mode 100644 index ca7e3a38..00000000 Binary files a/shaders/hlsl/variablerateshading/scene.vert.spv and /dev/null differ diff --git a/shaders/hlsl/viewportarray/multiview.geom b/shaders/hlsl/viewportarray/multiview.geom deleted file mode 100644 index b1e609fd..00000000 --- a/shaders/hlsl/viewportarray/multiview.geom +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2020 Google LLC - -struct UBO -{ - float4x4 projection[2]; - float4x4 modelview[2]; - float4 lightPos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -}; - -struct GSOutput -{ - float4 Pos : SV_POSITION; - uint ViewportIndex : SV_ViewportArrayIndex; - uint PrimitiveID : SV_PrimitiveID; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOOR1; -[[vk::location(3)]] float3 LightVec : TEXCOOR2; -}; - -[maxvertexcount(3)] -[instance(2)] -void main(triangle VSOutput input[3], inout TriangleStream outStream, uint InvocationID : SV_GSInstanceID, uint PrimitiveID : SV_PrimitiveID) -{ - for(int i = 0; i < 3; i++) - { - GSOutput output = (GSOutput)0; - output.Normal = mul((float3x3)ubo.modelview[InvocationID], input[i].Normal); - output.Color = input[i].Color; - - float4 pos = input[i].Pos; - float4 worldPos = mul(ubo.modelview[InvocationID], pos); - - float3 lPos = mul(ubo.modelview[InvocationID], ubo.lightPos).xyz; - output.LightVec = lPos - worldPos.xyz; - output.ViewVec = -worldPos.xyz; - - output.Pos = mul(ubo.projection[InvocationID], worldPos); - - // Set the viewport index that the vertex will be emitted to - output.ViewportIndex = InvocationID; - output.PrimitiveID = PrimitiveID; - outStream.Append( output ); - } - - outStream.RestartStrip(); -} \ No newline at end of file diff --git a/shaders/hlsl/viewportarray/multiview.geom.spv b/shaders/hlsl/viewportarray/multiview.geom.spv deleted file mode 100644 index da192bb1..00000000 Binary files a/shaders/hlsl/viewportarray/multiview.geom.spv and /dev/null differ diff --git a/shaders/hlsl/viewportarray/scene.frag b/shaders/hlsl/viewportarray/scene.frag deleted file mode 100644 index 189e9955..00000000 --- a/shaders/hlsl/viewportarray/scene.frag +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Google LLC - -struct GSOutput -{ -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -[[vk::location(2)]] float3 ViewVec : TEXCOORD1; -[[vk::location(3)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(GSOutput input) : SV_TARGET -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.1, 0.1, 0.1); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/hlsl/viewportarray/scene.frag.spv b/shaders/hlsl/viewportarray/scene.frag.spv deleted file mode 100644 index a2843e1c..00000000 Binary files a/shaders/hlsl/viewportarray/scene.frag.spv and /dev/null differ diff --git a/shaders/hlsl/viewportarray/scene.vert b/shaders/hlsl/viewportarray/scene.vert deleted file mode 100644 index 1aeca832..00000000 --- a/shaders/hlsl/viewportarray/scene.vert +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 Normal : NORMAL0; -[[vk::location(1)]] float3 Color : COLOR0; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Normal = input.Normal; - output.Pos = float4(input.Pos.xyz, 1.0); - return output; -} diff --git a/shaders/hlsl/viewportarray/scene.vert.spv b/shaders/hlsl/viewportarray/scene.vert.spv deleted file mode 100644 index 54e85bda..00000000 Binary files a/shaders/hlsl/viewportarray/scene.vert.spv and /dev/null differ diff --git a/shaders/hlsl/vulkanscene/logo.frag b/shaders/hlsl/vulkanscene/logo.frag deleted file mode 100644 index e4a8c9df..00000000 --- a/shaders/hlsl/vulkanscene/logo.frag +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSOutput -{ -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 EyePos : POSITION0; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float4 main(VSOutput input) : SV_TARGET -{ - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - - float4 diff = float4(input.Color, 1.0) * max(dot(input.Normal, input.LightVec), 0.0); - float shininess = 0.0; - float4 spec = float4(1.0, 1.0, 1.0, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 2.5) * shininess; - - return float4((diff + spec).rgb, 1); -} \ No newline at end of file diff --git a/shaders/hlsl/vulkanscene/logo.frag.spv b/shaders/hlsl/vulkanscene/logo.frag.spv deleted file mode 100644 index 8408252e..00000000 Binary files a/shaders/hlsl/vulkanscene/logo.frag.spv and /dev/null differ diff --git a/shaders/hlsl/vulkanscene/logo.vert b/shaders/hlsl/vulkanscene/logo.vert deleted file mode 100644 index dc458eee..00000000 --- a/shaders/hlsl/vulkanscene/logo.vert +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 TexCoord : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 normal; - float4x4 view; - float3 lightpos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 EyePos : POSITION0; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - float4x4 modelView = mul(ubo.view, ubo.model); - float4 pos = mul(modelView, input.Pos); - output.UV = input.TexCoord.xy; - output.Normal = normalize(mul((float3x3)ubo.normal, input.Normal)); - output.Color = input.Color; - output.Pos = mul(ubo.projection, pos); - output.EyePos = mul(modelView, pos).xyz; - float4 lightPos = mul(modelView, float4(1.0, 2.0, 0.0, 1.0)); - output.LightVec = normalize(lightPos.xyz - output.EyePos); - return output; -} diff --git a/shaders/hlsl/vulkanscene/logo.vert.spv b/shaders/hlsl/vulkanscene/logo.vert.spv deleted file mode 100644 index 1c78bd85..00000000 Binary files a/shaders/hlsl/vulkanscene/logo.vert.spv and /dev/null differ diff --git a/shaders/hlsl/vulkanscene/mesh.frag b/shaders/hlsl/vulkanscene/mesh.frag deleted file mode 100644 index 5770537a..00000000 --- a/shaders/hlsl/vulkanscene/mesh.frag +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2020 Google LLC - -Texture2D tex : register(t1); -SamplerState samp : register(s1); - -struct VSOutput -{ -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 EyePos : POSITION0; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -float specpart(float3 L, float3 N, float3 H) -{ - if (dot(N, L) > 0.0) - { - return pow(clamp(dot(H, N), 0.0, 1.0), 64.0); - } - return 0.0; -} - -float4 main(VSOutput input) : SV_TARGET -{ - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - - float3 halfVec = normalize(input.LightVec + input.EyePos); - float diff = clamp(dot(input.LightVec, input.Normal), 0.0, 1.0); - float spec = specpart(input.LightVec, input.Normal, halfVec); - float intensity = 0.1 + diff + spec; - - float4 IAmbient = float4(0.2, 0.2, 0.2, 1.0); - float4 IDiffuse = float4(0.5, 0.5, 0.5, 0.5) * max(dot(input.Normal, input.LightVec), 0.0); - float shininess = 0.75; - float4 ISpecular = float4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 2.0) * shininess; - - float4 outFragColor = float4((IAmbient + IDiffuse) * float4(input.Color, 1.0) + ISpecular); - - // Some manual saturation - if (intensity > 0.95) - outFragColor *= 2.25; - if (intensity < 0.15) - outFragColor = float4(0.1, 0.1, 0.1, 0.1); - - return outFragColor; -} \ No newline at end of file diff --git a/shaders/hlsl/vulkanscene/mesh.frag.spv b/shaders/hlsl/vulkanscene/mesh.frag.spv deleted file mode 100644 index 21cf637e..00000000 Binary files a/shaders/hlsl/vulkanscene/mesh.frag.spv and /dev/null differ diff --git a/shaders/hlsl/vulkanscene/mesh.vert b/shaders/hlsl/vulkanscene/mesh.vert deleted file mode 100644 index 77490e46..00000000 --- a/shaders/hlsl/vulkanscene/mesh.vert +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ -[[vk::location(0)]] float4 Pos : POSITION0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float2 TexCoord : TEXCOORD0; -[[vk::location(3)]] float3 Color : COLOR0; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 normal; - float4x4 view; - float3 lightpos; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float3 Normal : NORMAL0; -[[vk::location(2)]] float3 Color : COLOR0; -[[vk::location(3)]] float3 EyePos : POSITION0; -[[vk::location(4)]] float3 LightVec : TEXCOORD2; -}; - -VSOutput main(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.UV = input.TexCoord.xy; - output.Normal = normalize(mul((float3x3)ubo.normal, input.Normal)); - output.Color = input.Color; - float4x4 modelView = mul(ubo.view, ubo.model); - float4 pos = mul(modelView, input.Pos); - output.Pos = mul(ubo.projection, pos); - output.EyePos = mul(modelView, pos).xyz; - float4 lightPos = mul(modelView, float4(ubo.lightpos, 1.0)); - output.LightVec = normalize(lightPos.xyz - output.EyePos); - return output; -} diff --git a/shaders/hlsl/vulkanscene/mesh.vert.spv b/shaders/hlsl/vulkanscene/mesh.vert.spv deleted file mode 100644 index b621bf60..00000000 Binary files a/shaders/hlsl/vulkanscene/mesh.vert.spv and /dev/null differ diff --git a/shaders/hlsl/vulkanscene/skybox.frag b/shaders/hlsl/vulkanscene/skybox.frag deleted file mode 100644 index bd2ba96d..00000000 --- a/shaders/hlsl/vulkanscene/skybox.frag +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 Google LLC - -TextureCube textureCubeMap : register(t1); -SamplerState samplerCubeMap : register(s1); - -float4 main([[vk::location(0)]] float3 inUVW : TEXCOORD0) : SV_TARGET -{ - return textureCubeMap.Sample(samplerCubeMap, inUVW); -} \ No newline at end of file diff --git a/shaders/hlsl/vulkanscene/skybox.frag.spv b/shaders/hlsl/vulkanscene/skybox.frag.spv deleted file mode 100644 index 44379774..00000000 Binary files a/shaders/hlsl/vulkanscene/skybox.frag.spv and /dev/null differ diff --git a/shaders/hlsl/vulkanscene/skybox.vert b/shaders/hlsl/vulkanscene/skybox.vert deleted file mode 100644 index 2b9d52ae..00000000 --- a/shaders/hlsl/vulkanscene/skybox.vert +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 Google LLC -// Copyright 2023 Sascha Willems - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 normal; - float4x4 view; -}; - -cbuffer ubo : register(b0) { UBO ubo; } - -struct VSOutput -{ - float4 Pos : SV_POSITION; -[[vk::location(0)]] float3 UVW : TEXCOORD0; -}; - -VSOutput main([[vk::location(0)]] float3 Pos : POSITION0) -{ - VSOutput output = (VSOutput)0; - - // Remove translation from view matrix - float4x4 viewMat = ubo.view; - viewMat[0][3] = 0.0; - viewMat[1][3] = 0.0; - viewMat[2][3] = 0.0; - output.UVW = Pos; - output.Pos = mul(ubo.projection, mul(viewMat, mul(ubo.model, float4(Pos.xyz, 1.0)))); - - return output; -} diff --git a/shaders/hlsl/vulkanscene/skybox.vert.spv b/shaders/hlsl/vulkanscene/skybox.vert.spv deleted file mode 100644 index 0d4d3618..00000000 Binary files a/shaders/hlsl/vulkanscene/skybox.vert.spv and /dev/null differ diff --git a/shaders/slang/_rename.py b/shaders/slang/_rename.py deleted file mode 100644 index bce6121e..00000000 --- a/shaders/slang/_rename.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (C) 2025 by Sascha Willems - www.saschawillems.de -# This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - -from shutil import move - -# To match required file names to fother shading languages that don't support multiple entry points, shader files may need to be renamed for some samples -def checkRenameFiles(samplename): - mappings = {} - match samplename: - case "displacement": - mappings = { - "displacement.vert.spv": "base.vert.spv", - "displacement.frag.spv": "base.frag.spv", - } - case "geometryshader": - mappings = { - "normaldebug.vert.spv": "base.vert.spv", - "normaldebug.frag.spv": "base.frag.spv", - } - case "graphicspipelinelibrary": - mappings = { - "uber.vert.spv": "shared.vert.spv", - } - case "raytracingbasic": - mappings = { - "raytracingbasic.rchit.spv": "closesthit.rchit.spv", - "raytracingbasic.rmiss.spv": "miss.rmiss.spv", - "raytracingbasic.rgen.spv": "raygen.rgen.spv", - } - case "raytracingcallable": - mappings = { - "raytracingcallable.rchit.spv": "closesthit.rchit.spv", - "raytracingcallable.rmiss.spv": "miss.rmiss.spv", - "raytracingcallable.rgen.spv": "raygen.rgen.spv", - } - case "raytracinggltf": - mappings = { - "raytracinggltf.rchit.spv": "closesthit.rchit.spv", - "raytracinggltf.rmiss.spv": "miss.rmiss.spv", - "raytracinggltf.rgen.spv": "raygen.rgen.spv", - "raytracinggltf.rahit.spv": "anyhit.rahit.spv", - } - case "raytracingpositionfetch": - mappings = { - "raytracingpositionfetch.rchit.spv": "closesthit.rchit.spv", - "raytracingpositionfetch.rmiss.spv": "miss.rmiss.spv", - "raytracingpositionfetch.rgen.spv": "raygen.rgen.spv", - } - case "raytracingreflections": - mappings = { - "raytracingreflections.rchit.spv": "closesthit.rchit.spv", - "raytracingreflections.rmiss.spv": "miss.rmiss.spv", - "raytracingreflections.rgen.spv": "raygen.rgen.spv", - } - case "raytracingsbtdata": - mappings = { - "raytracingsbtdata.rchit.spv": "closesthit.rchit.spv", - "raytracingsbtdata.rmiss.spv": "miss.rmiss.spv", - "raytracingsbtdata.rgen.spv": "raygen.rgen.spv", - } - case "raytracingshadows": - mappings = { - "raytracingshadows.rchit.spv": "closesthit.rchit.spv", - "raytracingshadows.rmiss.spv": "miss.rmiss.spv", - "raytracingshadows.rgen.spv": "raygen.rgen.spv", - } - case "raytracingtextures": - mappings = { - "raytracingtextures.rchit.spv": "closesthit.rchit.spv", - "raytracingtextures.rmiss.spv": "miss.rmiss.spv", - "raytracingtextures.rgen.spv": "raygen.rgen.spv", - "raytracingtextures.rahit.spv": "anyhit.rahit.spv", - } - case "raytracingintersection": - mappings = { - "raytracingintersection.rchit.spv": "closesthit.rchit.spv", - "raytracingintersection.rmiss.spv": "miss.rmiss.spv", - "raytracingintersection.rgen.spv": "raygen.rgen.spv", - "raytracingintersection.rint.spv": "intersection.rint.spv", - } - case "viewportarray": - mappings = { - "scene.geom.spv": "multiview.geom.spv", - } - for x, y in mappings.items(): - move(samplename + "\\" + x, samplename + "\\" + y) diff --git a/shaders/slang/base/uioverlay.frag.spv b/shaders/slang/base/uioverlay.frag.spv deleted file mode 100644 index 9909fbc8..00000000 Binary files a/shaders/slang/base/uioverlay.frag.spv and /dev/null differ diff --git a/shaders/slang/base/uioverlay.slang b/shaders/slang/base/uioverlay.slang deleted file mode 100644 index d59b67b6..00000000 --- a/shaders/slang/base/uioverlay.slang +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -Sampler2D fontTexture; - -struct VSInput -{ - float2 Pos : POSITION0; - float2 UV; - float4 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float4 Color; -}; - -struct PushConstants -{ - float2 scale; - float2 translate; -}; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform PushConstants pushConstants) -{ - VSOutput output; - output.Pos = float4(input.Pos * pushConstants.scale + pushConstants.translate, 0.0, 1.0); - output.UV = input.UV; - output.Color = input.Color; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return input.Color * fontTexture.Sample(input.UV); -} \ No newline at end of file diff --git a/shaders/slang/base/uioverlay.vert.spv b/shaders/slang/base/uioverlay.vert.spv deleted file mode 100644 index 6eacc026..00000000 Binary files a/shaders/slang/base/uioverlay.vert.spv and /dev/null differ diff --git a/shaders/slang/bloom/colorpass.frag.spv b/shaders/slang/bloom/colorpass.frag.spv deleted file mode 100644 index 81761f27..00000000 Binary files a/shaders/slang/bloom/colorpass.frag.spv and /dev/null differ diff --git a/shaders/slang/bloom/colorpass.slang b/shaders/slang/bloom/colorpass.slang deleted file mode 100644 index 40ada51e..00000000 --- a/shaders/slang/bloom/colorpass.slang +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer ubo; - -Sampler2D colorMapSampler; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(input.Color, 1); -} \ No newline at end of file diff --git a/shaders/slang/bloom/colorpass.vert.spv b/shaders/slang/bloom/colorpass.vert.spv deleted file mode 100644 index cf45c930..00000000 Binary files a/shaders/slang/bloom/colorpass.vert.spv and /dev/null differ diff --git a/shaders/slang/bloom/gaussblur.frag.spv b/shaders/slang/bloom/gaussblur.frag.spv deleted file mode 100644 index ad8c7f46..00000000 Binary files a/shaders/slang/bloom/gaussblur.frag.spv and /dev/null differ diff --git a/shaders/slang/bloom/gaussblur.slang b/shaders/slang/bloom/gaussblur.slang deleted file mode 100644 index e381a27a..00000000 --- a/shaders/slang/bloom/gaussblur.slang +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -struct UBO -{ - float blurScale; - float blurStrength; -}; -ConstantBuffer ubo; - -Sampler2D samplerColor; - -[[SpecializationConstant]] const int blurdirection = 0; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float weight[5]; - weight[0] = 0.227027; - weight[1] = 0.1945946; - weight[2] = 0.1216216; - weight[3] = 0.054054; - weight[4] = 0.016216; - - float2 textureSize; - samplerColor.GetDimensions(textureSize.x, textureSize.y); - float2 tex_offset = 1.0 / textureSize * ubo.blurScale; // gets size of single texel - float3 result = samplerColor.Sample(input.UV).rgb * weight[0]; // current fragment's contribution - for(int i = 1; i < 5; ++i) - { - if (blurdirection == 1) - { - // H - result += samplerColor.Sample(input.UV + float2(tex_offset.x * i, 0.0)).rgb * weight[i] * ubo.blurScale; - result += samplerColor.Sample(input.UV - float2(tex_offset.x * i, 0.0)).rgb * weight[i] * ubo.blurScale; - } - else - { - // V - result += samplerColor.Sample(input.UV + float2(0.0, tex_offset.y * i)).rgb * weight[i] * ubo.blurScale; - result += samplerColor.Sample(input.UV - float2(0.0, tex_offset.y * i)).rgb * weight[i] * ubo.blurScale; - } - } - return float4(result, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/bloom/gaussblur.vert.spv b/shaders/slang/bloom/gaussblur.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/bloom/gaussblur.vert.spv and /dev/null differ diff --git a/shaders/slang/bloom/phongpass.frag.spv b/shaders/slang/bloom/phongpass.frag.spv deleted file mode 100644 index ae4d137d..00000000 Binary files a/shaders/slang/bloom/phongpass.frag.spv and /dev/null differ diff --git a/shaders/slang/bloom/phongpass.slang b/shaders/slang/bloom/phongpass.slang deleted file mode 100644 index 8d581753..00000000 --- a/shaders/slang/bloom/phongpass.slang +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float2 UV; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer ubo; - -Sampler2D colorMapSampler; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos))); - - float3 lightPos = float3(-5.0, -5.0, 0.0); - float4 pos = mul(ubo.view, mul(ubo.model, input.Pos)); - output.Normal = mul((float4x3)mul(ubo.view, ubo.model), input.Normal).xyz; - output.LightVec = lightPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 ambient = float3(0.0f, 0.0f, 0.0f); - - // Adjust light calculations for glow color - if ((input.Color.r >= 0.9) || (input.Color.g >= 0.9) || (input.Color.b >= 0.9)) - { - ambient = input.Color * 0.25; - } - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.75f, 0.75f, 0.75f); - return float4(ambient + diffuse + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/bloom/phongpass.vert.spv b/shaders/slang/bloom/phongpass.vert.spv deleted file mode 100644 index b606f32c..00000000 Binary files a/shaders/slang/bloom/phongpass.vert.spv and /dev/null differ diff --git a/shaders/slang/bloom/skybox.frag.spv b/shaders/slang/bloom/skybox.frag.spv deleted file mode 100644 index 71e6a035..00000000 Binary files a/shaders/slang/bloom/skybox.frag.spv and /dev/null differ diff --git a/shaders/slang/bloom/skybox.slang b/shaders/slang/bloom/skybox.slang deleted file mode 100644 index 3b21695b..00000000 --- a/shaders/slang/bloom/skybox.slang +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; -} - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer ubo; - -SamplerCube samplerCubeMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UVW = input.Pos; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerCubeMap.Sample(input.UVW); -} \ No newline at end of file diff --git a/shaders/slang/bloom/skybox.vert.spv b/shaders/slang/bloom/skybox.vert.spv deleted file mode 100644 index 65dde5e3..00000000 Binary files a/shaders/slang/bloom/skybox.vert.spv and /dev/null differ diff --git a/shaders/slang/bufferdeviceaddress/cube.frag.spv b/shaders/slang/bufferdeviceaddress/cube.frag.spv deleted file mode 100644 index 534ec32d..00000000 Binary files a/shaders/slang/bufferdeviceaddress/cube.frag.spv and /dev/null differ diff --git a/shaders/slang/bufferdeviceaddress/cube.slang b/shaders/slang/bufferdeviceaddress/cube.slang deleted file mode 100644 index 4e86556a..00000000 --- a/shaders/slang/bufferdeviceaddress/cube.slang +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -Sampler2D samplerColorMap; - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct MatrixReference { - float4x4 matrix; -}; - -struct PushConsts { - // Pointer to the buffer with the scene's MVP matrix - ConstBufferPointer sceneDataReference; - // Pointer to the buffer for the data for each model - ConstBufferPointer modelDataReference; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; -}; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform PushConsts pushConstants) -{ - MatrixReference sceneData = pushConstants.sceneDataReference.get(); - MatrixReference modelData = pushConstants.modelDataReference.get(); - - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(sceneData.matrix, mul(modelData.matrix, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/bufferdeviceaddress/cube.vert.spv b/shaders/slang/bufferdeviceaddress/cube.vert.spv deleted file mode 100644 index 200698c5..00000000 Binary files a/shaders/slang/bufferdeviceaddress/cube.vert.spv and /dev/null differ diff --git a/shaders/slang/compileshaders.py b/shaders/slang/compileshaders.py deleted file mode 100644 index c2e20149..00000000 --- a/shaders/slang/compileshaders.py +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright (C) 2025 by Sascha Willems - www.saschawillems.de -# This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) - -import argparse -import fileinput -import os -import subprocess -import sys -from _rename import * - -parser = argparse.ArgumentParser(description='Compile all slang shaders') -parser.add_argument('--slangc', type=str, help='path to slangc executable') -parser.add_argument('--sample', type=str, help='can be used to compile shaders for a single sample only') -args = parser.parse_args() - -def findCompiler(): - def isExe(path): - return os.path.isfile(path) and os.access(path, os.X_OK) - - if args.slangc != None and isExe(args.slangc): - return args.slangc - - exe_name = "slangc" - if os.name == "nt": - exe_name += ".exe" - - for exe_dir in os.environ["PATH"].split(os.pathsep): - full_path = os.path.join(exe_dir, exe_name) - if isExe(full_path): - return full_path - - sys.exit("Could not find slangc executable on PATH, and was not specified with --slangc") - -def getShaderStages(filename): - stages = [] - with open(filename) as f: - filecontent = f.read() - if '[shader("vertex")]' in filecontent: - stages.append("vertex") - if '[shader("fragment")]' in filecontent: - stages.append("fragment") - if '[shader("raygeneration")]' in filecontent: - stages.append("raygeneration") - if '[shader("miss")]' in filecontent: - stages.append("miss") - if '[shader("closesthit")]' in filecontent: - stages.append("closesthit") - if '[shader("callable")]' in filecontent: - stages.append("callable") - if '[shader("intersection")]' in filecontent: - stages.append("intersection") - if '[shader("anyhit")]' in filecontent: - stages.append("anyhit") - if '[shader("compute")]' in filecontent: - stages.append("compute") - if '[shader("amplification")]' in filecontent: - stages.append("amplification") - if '[shader("mesh")]' in filecontent: - stages.append("mesh") - if '[shader("geometry")]' in filecontent: - stages.append("geometry") - if '[shader("hull")]' in filecontent: - stages.append("hull") - if '[shader("domain")]' in filecontent: - stages.append("domain") - f.close() - return stages - -compiler_path = findCompiler() - -print("Found slang compiler at %s", compiler_path) - -compile_single_sample = "" -if args.sample != None: - compile_single_sample = args.sample - if (not os.path.isdir(compile_single_sample)): - print("ERROR: No directory found with name %s" % compile_single_sample) - exit(-1) - -dir_path = os.path.dirname(os.path.realpath(__file__)) -dir_path = dir_path.replace('\\', '/') -for root, dirs, files in os.walk(dir_path): - folder_name = os.path.basename(root) - if (compile_single_sample != "" and folder_name != compile_single_sample): - continue - for file in files: - if file.endswith(".slang"): - input_file = os.path.join(root, file) - # Slang can store multiple shader stages in a single file, we need to split into separate SPIR-V files for the sample framework - stages = getShaderStages(input_file) - print("Compiling %s" % input_file) - output_base_file_name = input_file - for stage in stages: - entry_point = stage + "Main" - output_ext = "" - match stage: - case "vertex": - output_ext = ".vert" - case "fragment": - output_ext = ".frag" - case "raygeneration": - output_ext = ".rgen" - case "miss": - output_ext = ".rmiss" - case "closesthit": - output_ext = ".rchit" - case "callable": - output_ext = ".rcall" - case "intersection": - output_ext = ".rint" - case "anyhit": - output_ext = ".rahit" - case "compute": - output_ext = ".comp" - case "mesh": - output_ext = ".mesh" - case "amplification": - output_ext = ".task" - case "geometry": - output_ext = ".geom" - case "hull": - output_ext = ".tesc" - case "domain": - output_ext = ".tese" - output_file = output_base_file_name + output_ext + ".spv" - output_file = output_file.replace(".slang", "") - print(output_file) - res = subprocess.call("%s %s -profile spirv_1_4 -matrix-layout-column-major -target spirv -o %s -entry %s -stage %s -warnings-disable 39001" % (compiler_path, input_file, output_file, entry_point, stage), shell=True) - if res != 0: - print("Error %s", res) - sys.exit(res) - checkRenameFiles(folder_name) \ No newline at end of file diff --git a/shaders/slang/computecloth/cloth.comp.spv b/shaders/slang/computecloth/cloth.comp.spv deleted file mode 100644 index 5f668990..00000000 Binary files a/shaders/slang/computecloth/cloth.comp.spv and /dev/null differ diff --git a/shaders/slang/computecloth/cloth.frag.spv b/shaders/slang/computecloth/cloth.frag.spv deleted file mode 100644 index 0cf50a1c..00000000 Binary files a/shaders/slang/computecloth/cloth.frag.spv and /dev/null differ diff --git a/shaders/slang/computecloth/cloth.slang b/shaders/slang/computecloth/cloth.slang deleted file mode 100644 index 80e53606..00000000 --- a/shaders/slang/computecloth/cloth.slang +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float3 Normal; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; -}; -[[vk::binding(0,0)]] ConstantBuffer ubo; -[[vk::binding(1,0)]] Sampler2D samplerColor; - -struct Particle { - float4 pos; - float4 vel; - float4 uv; - float4 normal; -}; - -[[vk::binding(0,0)]] StructuredBuffer particleIn; -[[vk::binding(1,0)]] RWStructuredBuffer particleOut; - -struct UBOCompute -{ - float deltaT; - float particleMass; - float springStiffness; - float damping; - float restDistH; - float restDistV; - float restDistD; - float sphereRadius; - float4 spherePos; - float4 gravity; - int2 particleCount; -}; -[[vk::binding(2, 0)]] ConstantBuffer params; - -float3 springForce(float3 p0, float3 p1, float restDist) -{ - float3 dist = p0 - p1; - return normalize(dist) * params.springStiffness * (length(dist) - restDist); -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - output.Normal = input.Normal.xyz; - float4 eyePos = mul(ubo.modelview, float4(input.Pos.x, input.Pos.y, input.Pos.z, 1.0)); - output.Pos = mul(ubo.projection, eyePos); - float4 pos = float4(input.Pos, 1.0); - float3 lPos = ubo.lightPos.xyz; - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 color = samplerColor.Sample(input.UV).rgb; - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.15) * float3(1, 1, 1); - float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.2, 0.2, 0.2); - return float4(diffuse * color.rgb + specular, 1.0); -} - -[shader("compute")] -[numthreads(10, 10, 1)] -void computeMain(uint3 id: SV_DispatchThreadID, uniform uint calculateNormals) -{ - uint index = id.y * params.particleCount.x + id.x; - if (index > params.particleCount.x * params.particleCount.y) - return; - - // Initial force from gravity - float3 force = params.gravity.xyz * params.particleMass; - - float3 pos = particleIn[index].pos.xyz; - float3 vel = particleIn[index].vel.xyz; - - // Spring forces from neighboring particles - // left - if (id.x > 0) { - force += springForce(particleIn[index-1].pos.xyz, pos, params.restDistH); - } - // right - if (id.x < params.particleCount.x - 1) { - force += springForce(particleIn[index + 1].pos.xyz, pos, params.restDistH); - } - // upper - if (id.y < params.particleCount.y - 1) { - force += springForce(particleIn[index + params.particleCount.x].pos.xyz, pos, params.restDistV); - } - // lower - if (id.y > 0) { - force += springForce(particleIn[index - params.particleCount.x].pos.xyz, pos, params.restDistV); - } - // upper-left - if ((id.x > 0) && (id.y < params.particleCount.y - 1)) { - force += springForce(particleIn[index + params.particleCount.x - 1].pos.xyz, pos, params.restDistD); - } - // lower-left - if ((id.x > 0) && (id.y > 0)) { - force += springForce(particleIn[index - params.particleCount.x - 1].pos.xyz, pos, params.restDistD); - } - // upper-right - if ((id.x < params.particleCount.x - 1) && (id.y < params.particleCount.y - 1)) { - force += springForce(particleIn[index + params.particleCount.x + 1].pos.xyz, pos, params.restDistD); - } - // lower-right - if ((id.x < params.particleCount.x - 1) && (id.y > 0)) { - force += springForce(particleIn[index - params.particleCount.x + 1].pos.xyz, pos, params.restDistD); - } - - force += (-params.damping * vel); - - // Integrate - float3 f = force * (1.0 / params.particleMass); - particleOut[index].pos = float4(pos + vel * params.deltaT + 0.5 * f * params.deltaT * params.deltaT, 1.0); - particleOut[index].vel = float4(vel + f * params.deltaT, 0.0); - - // Sphere collision - float3 sphereDist = particleOut[index].pos.xyz - params.spherePos.xyz; - if (length(sphereDist) < params.sphereRadius + 0.01) { - // If the particle is inside the sphere, push it to the outer radius - particleOut[index].pos.xyz = params.spherePos.xyz + normalize(sphereDist) * (params.sphereRadius + 0.01); - // Cancel out velocity - particleOut[index].vel = float4(0, 0, 0, 0); - } - - // Normals - if (calculateNormals == 1) { - float3 normal = float3(0, 0, 0); - float3 a, b, c; - if (id.y > 0) { - if (id.x > 0) { - a = particleIn[index - 1].pos.xyz - pos; - b = particleIn[index - params.particleCount.x - 1].pos.xyz - pos; - c = particleIn[index - params.particleCount.x].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - if (id.x < params.particleCount.x - 1) { - a = particleIn[index - params.particleCount.x].pos.xyz - pos; - b = particleIn[index - params.particleCount.x + 1].pos.xyz - pos; - c = particleIn[index + 1].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - } - if (id.y < params.particleCount.y - 1) { - if (id.x > 0) { - a = particleIn[index + params.particleCount.x].pos.xyz - pos; - b = particleIn[index + params.particleCount.x - 1].pos.xyz - pos; - c = particleIn[index - 1].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - if (id.x < params.particleCount.x - 1) { - a = particleIn[index + 1].pos.xyz - pos; - b = particleIn[index + params.particleCount.x + 1].pos.xyz - pos; - c = particleIn[index + params.particleCount.x].pos.xyz - pos; - normal += cross(a,b) + cross(b,c); - } - } - particleOut[index].normal = float4(normalize(normal), 0.0f); - } -} \ No newline at end of file diff --git a/shaders/slang/computecloth/cloth.vert.spv b/shaders/slang/computecloth/cloth.vert.spv deleted file mode 100644 index 38bd3b78..00000000 Binary files a/shaders/slang/computecloth/cloth.vert.spv and /dev/null differ diff --git a/shaders/slang/computecloth/sphere.frag.spv b/shaders/slang/computecloth/sphere.frag.spv deleted file mode 100644 index c06d4608..00000000 Binary files a/shaders/slang/computecloth/sphere.frag.spv and /dev/null differ diff --git a/shaders/slang/computecloth/sphere.slang b/shaders/slang/computecloth/sphere.slang deleted file mode 100644 index 99959727..00000000 --- a/shaders/slang/computecloth/sphere.slang +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - float4 eyePos = mul(ubo.modelview, float4(input.Pos.x, input.Pos.y, input.Pos.z, 1.0)); - output.Pos = mul(ubo.projection, eyePos); - float4 pos = float4(input.Pos, 1.0); - float3 lPos = ubo.lightPos.xyz; - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - output.Normal = input.Normal; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 color = float3(0.5, 0.5, 0.5); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.15); - float3 specular = pow(max(dot(R, V), 0.0), 32.0); - return float4(diffuse * color.rgb + specular, 1.0); -} diff --git a/shaders/slang/computecloth/sphere.vert.spv b/shaders/slang/computecloth/sphere.vert.spv deleted file mode 100644 index 377fb433..00000000 Binary files a/shaders/slang/computecloth/sphere.vert.spv and /dev/null differ diff --git a/shaders/slang/computecullandlod/cull.comp.spv b/shaders/slang/computecullandlod/cull.comp.spv deleted file mode 100644 index d004e4ff..00000000 Binary files a/shaders/slang/computecullandlod/cull.comp.spv and /dev/null differ diff --git a/shaders/slang/computecullandlod/cull.slang b/shaders/slang/computecullandlod/cull.slang deleted file mode 100644 index 16e1089e..00000000 --- a/shaders/slang/computecullandlod/cull.slang +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#define MAX_LOD_LEVEL_COUNT 6 -[[SpecializationConstant]] const int MAX_LOD_LEVEL = 5; - -struct InstanceData -{ - float3 pos; - float scale; -}; -StructuredBuffer instances; - -// Same layout as VkDrawIndexedIndirectCommand -struct IndexedIndirectCommand -{ - uint indexCount; - uint instanceCount; - uint firstIndex; - uint vertexOffset; - uint firstInstance; -}; -RWStructuredBuffer indirectDraws; - -// Binding 2: Uniform block object with matrices -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 cameraPos; - float4 frustumPlanes[6]; -}; -ConstantBuffer ubo; - -// Binding 3: Indirect draw stats -struct UBOOut -{ - uint drawCount; - uint lodCount[MAX_LOD_LEVEL_COUNT]; -}; -RWStructuredBuffer uboOut; - -// Binding 4: level-of-detail information -struct LOD -{ - uint firstIndex; - uint indexCount; - float distance; - float _pad0; -}; -StructuredBuffer lods; - -bool frustumCheck(float4 pos, float radius) -{ - // Check sphere against frustum planes - for (int i = 0; i < 6; i++) - { - if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0) - { - return false; - } - } - return true; -} - -[shader("compute")] -[numthreads(16, 1, 1)] -void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - uint idx = GlobalInvocationID.x; - uint temp; - - // Clear stats on first invocation - if (idx == 0) - { - InterlockedExchange(uboOut[0].drawCount, 0, temp); - for (uint i = 0; i < MAX_LOD_LEVEL + 1; i++) - { - InterlockedExchange(uboOut[0].lodCount[i], 0, temp); - } - } - - float4 pos = float4(instances[idx].pos.xyz, 1.0); - - // Check if object is within current viewing frustum - if (frustumCheck(pos, 1.0)) - { - indirectDraws[idx].instanceCount = 1; - - // Increase number of indirect draw counts - InterlockedAdd(uboOut[0].drawCount, 1, temp); - - // Select appropriate LOD level based on distance to camera - uint lodLevel = MAX_LOD_LEVEL; - for (uint i = 0; i < MAX_LOD_LEVEL; i++) - { - if (distance(instances[idx].pos.xyz, ubo.cameraPos.xyz) < lods[i].distance) - { - lodLevel = i; - break; - } - } - indirectDraws[idx].firstIndex = lods[lodLevel].firstIndex; - indirectDraws[idx].indexCount = lods[lodLevel].indexCount; - // Update stats - InterlockedAdd(uboOut[0].lodCount[lodLevel], 1, temp); - } - else - { - indirectDraws[idx].instanceCount = 0; - } -} \ No newline at end of file diff --git a/shaders/slang/computecullandlod/indirectdraw.frag.spv b/shaders/slang/computecullandlod/indirectdraw.frag.spv deleted file mode 100644 index c9d4cf3f..00000000 Binary files a/shaders/slang/computecullandlod/indirectdraw.frag.spv and /dev/null differ diff --git a/shaders/slang/computecullandlod/indirectdraw.slang b/shaders/slang/computecullandlod/indirectdraw.slang deleted file mode 100644 index d051bd6c..00000000 --- a/shaders/slang/computecullandlod/indirectdraw.slang +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos : POSITION0; - float3 Normal; - float3 Color; - // Instanced attributes - float3 instancePos; - float instanceScale; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Normal = input.Normal; - float4 pos = float4((input.Pos.xyz * input.instanceScale) + input.instancePos, 1.0); - output.Pos = mul(ubo.projection, mul(ubo.modelview, pos)); - float4 wPos = mul(ubo.modelview, float4(pos.xyz, 1.0)); - float4 lPos = float4(0.0, 10.0, 50.0, 1.0); - output.LightVec = lPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 ambient = float3(0.25, 0.25, 0.25); - float3 diffuse = max(dot(N, L), 0.0).xxx; - return float4((ambient + diffuse) * input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/computecullandlod/indirectdraw.vert.spv b/shaders/slang/computecullandlod/indirectdraw.vert.spv deleted file mode 100644 index 795c4dcb..00000000 Binary files a/shaders/slang/computecullandlod/indirectdraw.vert.spv and /dev/null differ diff --git a/shaders/slang/computeheadless/headless.comp.spv b/shaders/slang/computeheadless/headless.comp.spv deleted file mode 100644 index 83f37309..00000000 Binary files a/shaders/slang/computeheadless/headless.comp.spv and /dev/null differ diff --git a/shaders/slang/computeheadless/headless.slang b/shaders/slang/computeheadless/headless.slang deleted file mode 100644 index 7f5db02a..00000000 --- a/shaders/slang/computeheadless/headless.slang +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -RWStructuredBuffer values; - -[[SpecializationConstant]] const uint BUFFER_ELEMENTS = 32; - -uint fibonacci(uint n) { - if(n <= 1){ - return n; - } - uint curr = 1; - uint prev = 1; - for(uint i = 2; i < n; ++i) { - uint temp = curr; - curr += prev; - prev = temp; - } - return curr; -} - -[numthreads(1, 1, 1)] -[shader("compute")] -void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - uint index = GlobalInvocationID.x; - if (index >= BUFFER_ELEMENTS) - return; - values[index] = fibonacci(values[index]); -} - diff --git a/shaders/slang/computenbody/particle.frag.spv b/shaders/slang/computenbody/particle.frag.spv deleted file mode 100644 index f55ec7bb..00000000 Binary files a/shaders/slang/computenbody/particle.frag.spv and /dev/null differ diff --git a/shaders/slang/computenbody/particle.slang b/shaders/slang/computenbody/particle.slang deleted file mode 100644 index 15724781..00000000 --- a/shaders/slang/computenbody/particle.slang +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float4 Vel; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float PSize : SV_PointSize; - float GradientPos; - float2 CenterPos; - float PointSize; -}; - -Sampler2D samplerColorMap; -Sampler2D samplerGradientRamp; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float2 screendim; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - const float spriteSize = 0.005 * input.Pos.w; // Point size influenced by mass (stored in input.Pos.w); - - float4 eyePos = mul(ubo.modelview, float4(input.Pos.x, input.Pos.y, input.Pos.z, 1.0)); - float4 projectedCorner = mul(ubo.projection, float4(0.5 * spriteSize, 0.5 * spriteSize, eyePos.z, eyePos.w)); - output.PSize = output.PointSize = clamp(ubo.screendim.x * projectedCorner.x / projectedCorner.w, 1.0, 128.0); - - output.Pos = mul(ubo.projection, eyePos); - output.CenterPos = ((output.Pos.xy / output.Pos.w) + 1.0) * 0.5 * ubo.screendim; - - output.GradientPos = input.Vel.w; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 color = samplerGradientRamp.Sample(float2(input.GradientPos, 0.0)).rgb; - float2 PointCoord = (input.Pos.xy - input.CenterPos.xy) / input.PointSize + 0.5; - return float4(samplerColorMap.Sample(PointCoord).rgb * color, 1); -} diff --git a/shaders/slang/computenbody/particle.vert.spv b/shaders/slang/computenbody/particle.vert.spv deleted file mode 100644 index 6c165347..00000000 Binary files a/shaders/slang/computenbody/particle.vert.spv and /dev/null differ diff --git a/shaders/slang/computenbody/particle_calculate.comp.spv b/shaders/slang/computenbody/particle_calculate.comp.spv deleted file mode 100644 index 8df61f01..00000000 Binary files a/shaders/slang/computenbody/particle_calculate.comp.spv and /dev/null differ diff --git a/shaders/slang/computenbody/particle_calculate.slang b/shaders/slang/computenbody/particle_calculate.slang deleted file mode 100644 index e4ec9499..00000000 --- a/shaders/slang/computenbody/particle_calculate.slang +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Particle -{ - float4 pos; - float4 vel; -}; -// Binding 0 : Position storage buffer -RWStructuredBuffer particles; - -struct UBO -{ - float deltaT; - int particleCount; - float gravity; - float power; - float soften; -}; -ConstantBuffer ubo; - -#define MAX_SHARED_DATA_SIZE 1024 -[[SpecializationConstant]] const int SHARED_DATA_SIZE = 512; -[[SpecializationConstant]] const float GRAVITY = 0.002; -[[SpecializationConstant]] const float POWER = 0.75; -[[SpecializationConstant]] const float SOFTEN = 0.0075; - -// Share data between computer shader invocations to speed up caluclations -groupshared float4 sharedData[MAX_SHARED_DATA_SIZE]; - -[shader("compute")] -[numthreads(256, 1, 1)] -void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID, uint3 LocalInvocationID : SV_GroupThreadID) -{ - // Current SSBO index - uint index = GlobalInvocationID.x; - if (index >= ubo.particleCount) - return; - - float4 position = particles[index].pos; - float4 velocity = particles[index].vel; - float4 acceleration = float4(0, 0, 0, 0); - - for (int i = 0; i < ubo.particleCount; i += SHARED_DATA_SIZE) - { - if (i + LocalInvocationID.x < ubo.particleCount) - { - sharedData[LocalInvocationID.x] = particles[i + LocalInvocationID.x].pos; - } - else - { - sharedData[LocalInvocationID.x] = float4(0, 0, 0, 0); - } - - GroupMemoryBarrierWithGroupSync(); - - for (int j = 0; j < 256; j++) - { - float4 other = sharedData[j]; - float3 len = other.xyz - position.xyz; - acceleration.xyz += ubo.gravity * len * other.w / pow(dot(len, len) + ubo.soften, ubo.power); - } - - GroupMemoryBarrierWithGroupSync(); - } - - particles[index].vel.xyz += ubo.deltaT * acceleration.xyz; - - // Gradient texture position - particles[index].vel.w += 0.1 * ubo.deltaT; - if (particles[index].vel.w > 1.0) { - particles[index].vel.w -= 1.0; - } -} \ No newline at end of file diff --git a/shaders/slang/computenbody/particle_integrate.comp.spv b/shaders/slang/computenbody/particle_integrate.comp.spv deleted file mode 100644 index eb5178ea..00000000 Binary files a/shaders/slang/computenbody/particle_integrate.comp.spv and /dev/null differ diff --git a/shaders/slang/computenbody/particle_integrate.slang b/shaders/slang/computenbody/particle_integrate.slang deleted file mode 100644 index 484fe5d9..00000000 --- a/shaders/slang/computenbody/particle_integrate.slang +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Particle -{ - float4 pos; - float4 vel; -}; -// Binding 0 : Position storage buffer -RWStructuredBuffer particles; - -struct UBO -{ - float deltaT; - int particleCount; -}; -ConstantBuffer ubo; - -[shader("compute")] -[numthreads(256, 1, 1)] -void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - int index = int(GlobalInvocationID.x); - float4 position = particles[index].pos; - float4 velocity = particles[index].vel; - position += ubo.deltaT * velocity; - particles[index].pos = position; -} \ No newline at end of file diff --git a/shaders/slang/computeparticles/particle.comp.spv b/shaders/slang/computeparticles/particle.comp.spv deleted file mode 100644 index 739f548d..00000000 Binary files a/shaders/slang/computeparticles/particle.comp.spv and /dev/null differ diff --git a/shaders/slang/computeparticles/particle.frag.spv b/shaders/slang/computeparticles/particle.frag.spv deleted file mode 100644 index 0a5b51c5..00000000 Binary files a/shaders/slang/computeparticles/particle.frag.spv and /dev/null differ diff --git a/shaders/slang/computeparticles/particle.slang b/shaders/slang/computeparticles/particle.slang deleted file mode 100644 index 9eee978a..00000000 --- a/shaders/slang/computeparticles/particle.slang +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -[[vk::binding(0, 0)]] Sampler2D samplerColorMap; -[[vk::binding(1, 0)]] Sampler2D samplerGradientRamp; - -struct VSInput -{ - float2 Pos : POSITION0; - float4 GradientPos : POSITION1; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float PointSize : SV_PointSize; - float4 Color : COLOR0; - float GradientPos : POSITION0; -}; - -struct Particle -{ - float2 pos; - float2 vel; - float4 gradientPos; -}; -// Binding 0 : Position storage buffer -[[vk::binding(0, 0)]] RWStructuredBuffer particles; - -struct UBO -{ - float deltaT; - float destX; - float destY; - int particleCount; -}; -[[vk::binding(1, 0)]] ConstantBuffer ubo; - -struct PushConsts -{ - float2 screendim; -}; - -float2 attraction(float2 pos, float2 attractPos) -{ - float2 delta = attractPos - pos; - const float damp = 0.5; - float dDampedDot = dot(delta, delta) + damp; - float invDist = 1.0f / sqrt(dDampedDot); - float invDistCubed = invDist*invDist*invDist; - return delta * invDistCubed * 0.0035; -} - -float2 repulsion(float2 pos, float2 attractPos) -{ - float2 delta = attractPos - pos; - float targetDistance = sqrt(dot(delta, delta)); - return delta * (1.0 / (targetDistance * targetDistance * targetDistance)) * -0.000035; -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.PointSize = 8.0; - output.Color = float4(0.035, 0.035, 0.035, 0.035); - output.GradientPos = input.GradientPos.x; - output.Pos = float4(input.Pos.xy, 1.0, 1.0); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input, float2 pointCoord: SV_PointCoord) -{ - float3 color = samplerGradientRamp.Sample(float2(input.GradientPos, 0.0)).rgb; - return float4(samplerColorMap.Sample(pointCoord).rgb * color, 1.0); -} - -[shader("compute")] -[numthreads(256, 1, 1)] -void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - // Current SSBO index - uint index = GlobalInvocationID.x; - // Don't try to write beyond particle count - if (index >= ubo.particleCount) { - return; - } - - // Read position and velocity - float2 vVel = particles[index].vel.xy; - float2 vPos = particles[index].pos.xy; - - float2 destPos = float2(ubo.destX, ubo.destY); - - float2 delta = destPos - vPos; - float targetDistance = sqrt(dot(delta, delta)); - vVel += repulsion(vPos, destPos.xy) * 0.05; - - // Move by velocity - vPos += vVel * ubo.deltaT; - - // collide with boundary - if ((vPos.x < -1.0) || (vPos.x > 1.0) || (vPos.y < -1.0) || (vPos.y > 1.0)) { - vVel = (-vVel * 0.1) + attraction(vPos, destPos) * 12; - } else { - particles[index].pos.xy = vPos; - } - - // Write back - particles[index].vel.xy = vVel; - particles[index].gradientPos.x += 0.02 * ubo.deltaT; - if (particles[index].gradientPos.x > 1.0) { - particles[index].gradientPos.x -= 1.0; - } -} - diff --git a/shaders/slang/computeparticles/particle.vert.spv b/shaders/slang/computeparticles/particle.vert.spv deleted file mode 100644 index e77a6d94..00000000 Binary files a/shaders/slang/computeparticles/particle.vert.spv and /dev/null differ diff --git a/shaders/slang/computeraytracing/raytracing.comp.spv b/shaders/slang/computeraytracing/raytracing.comp.spv deleted file mode 100644 index 59229188..00000000 Binary files a/shaders/slang/computeraytracing/raytracing.comp.spv and /dev/null differ diff --git a/shaders/slang/computeraytracing/raytracing.slang b/shaders/slang/computeraytracing/raytracing.slang deleted file mode 100644 index 6e55885c..00000000 --- a/shaders/slang/computeraytracing/raytracing.slang +++ /dev/null @@ -1,258 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -// Shader is looseley based on the ray tracing coding session by Inigo Quilez (www.iquilezles.org) - -#define EPSILON 0.0001 -#define MAXLEN 1000.0 -#define SHADOW 0.5 -#define RAYBOUNCES 2 -#define REFLECTIONS true -#define REFLECTIONSTRENGTH 0.4 -#define REFLECTIONFALLOFF 0.5 - -#define SceneObjectTypeSphere 0 -#define SceneObjectTypePlane 1 - -RWTexture2D resultImage; - -struct Camera -{ - float3 pos; - float3 lookat; - float fov; -}; - -struct UBO -{ - float3 lightPos; - float aspectRatio; - float4 fogColor; - Camera camera; - float4x4 rotMat; -}; -ConstantBuffer ubo; - -struct SceneObject -{ - float4 objectProperties; - float3 diffuse; - float specular; - int id; - int objectType; -}; -StructuredBuffer sceneObjects; - -void reflectRay(inout float3 rayD, in float3 mormal) -{ - rayD = rayD + 2.0 * -dot(mormal, rayD) * mormal; -} - -// Lighting ========================================================= - -float lightDiffuse(float3 normal, float3 lightDir) -{ - return clamp(dot(normal, lightDir), 0.1, 1.0); -} - -float lightSpecular(float3 normal, float3 lightDir, float specularFactor) -{ - float3 viewVec = normalize(ubo.camera.pos); - float3 halfVec = normalize(lightDir + viewVec); - return pow(clamp(dot(normal, halfVec), 0.0, 1.0), specularFactor); -} - -// Sphere =========================================================== - -float sphereIntersect(in float3 rayO, in float3 rayD, in SceneObject sphere) -{ - float3 oc = rayO - sphere.objectProperties.xyz; - float b = 2.0 * dot(oc, rayD); - float c = dot(oc, oc) - sphere.objectProperties.w * sphere.objectProperties.w; - float h = b*b - 4.0*c; - if (h < 0.0) - { - return -1.0; - } - float t = (-b - sqrt(h)) / 2.0; - - return t; -} - -float3 sphereNormal(in float3 pos, in SceneObject sphere) -{ - return (pos - sphere.objectProperties.xyz) / sphere.objectProperties.w; -} - -// Plane =========================================================== - -float planeIntersect(float3 rayO, float3 rayD, SceneObject plane) -{ - float d = dot(rayD, plane.objectProperties.xyz); - - if (d == 0.0) - return 0.0; - - float t = -(plane.objectProperties.w + dot(rayO, plane.objectProperties.xyz)) / d; - - if (t < 0.0) - return 0.0; - - return t; -} - - -int intersect(in float3 rayO, in float3 rayD, inout float resT) -{ - int id = -1; - float t = MAXLEN; - - uint sceneObjectsLength; - uint sceneObjectsStride; - sceneObjects.GetDimensions(sceneObjectsLength, sceneObjectsStride); - - for (int i = 0; i < sceneObjectsLength; i++) { - // Sphere - if (sceneObjects[i].objectType == SceneObjectTypeSphere) { - t = sphereIntersect(rayO, rayD, sceneObjects[i]); - } - // Plane - if (sceneObjects[i].objectType == SceneObjectTypePlane) { - t = planeIntersect(rayO, rayD, sceneObjects[i]); - } - if ((t > EPSILON) && (t < resT)) - { - id = sceneObjects[i].id; - resT = t; - } - } - - return id; -} - -float calcShadow(in float3 rayO, in float3 rayD, in int objectId, inout float t) -{ - uint sceneObjectsLength; - uint sceneObjectsStride; - sceneObjects.GetDimensions(sceneObjectsLength, sceneObjectsStride); - - for (int i = 0; i < sceneObjectsLength; i++) { - if (sceneObjects[i].id == objectId) - continue; - - float tLoc = MAXLEN; - - // Sphere - if (sceneObjects[i].objectType == SceneObjectTypeSphere) - { - tLoc = sphereIntersect(rayO, rayD, sceneObjects[i]); - } - // Plane - if (sceneObjects[i].objectType == SceneObjectTypePlane) - { - tLoc = planeIntersect(rayO, rayD, sceneObjects[i]); - } - if ((tLoc > EPSILON) && (tLoc < t)) - { - t = tLoc; - return SHADOW; - } - } - return 1.0; -} - -float3 fog(in float t, in float3 color) -{ - return lerp(color, ubo.fogColor.rgb, clamp(sqrt(t*t)/20.0, 0.0, 1.0)); -} - -float3 renderScene(inout float3 rayO, inout float3 rayD, inout int id) -{ - float3 color = float3(0, 0, 0); - float t = MAXLEN; - - // Get intersected object ID - int objectID = intersect(rayO, rayD, t); - - if (objectID == -1) - { - return color; - } - - float3 pos = rayO + t * rayD; - float3 lightVec = normalize(ubo.lightPos - pos); - float3 normal; - - uint sceneObjectsLength; - uint sceneObjectsStride; - sceneObjects.GetDimensions(sceneObjectsLength, sceneObjectsStride); - - for (int i = 0; i < sceneObjectsLength; i++) { - if (objectID == sceneObjects[i].id) - { - // Sphere - if (sceneObjects[i].objectType == SceneObjectTypeSphere) { - normal = sphereNormal(pos, sceneObjects[i]); - } - // Plane - if (sceneObjects[i].objectType == SceneObjectTypePlane) { - normal = sceneObjects[i].objectProperties.xyz; - } - // Lighting - float diffuse = lightDiffuse(normal, lightVec); - float specular = lightSpecular(normal, lightVec, sceneObjects[i].specular); - color = diffuse * sceneObjects[i].diffuse + specular; - } - } - - if (id == -1) - return color; - - id = objectID; - - // Shadows - t = length(ubo.lightPos - pos); - color *= calcShadow(pos, lightVec, id, t); - - // Fog - color = fog(t, color); - - // Reflect ray for next render pass - reflectRay(rayD, normal); - rayO = pos; - - return color; -} - -[shader("compute")] -[numthreads(16, 16, 1)] -void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - int2 dim; - resultImage.GetDimensions(dim.x, dim.y); - float2 uv = float2(GlobalInvocationID.xy) / dim; - - float3 rayO = ubo.camera.pos; - float3 rayD = normalize(float3((-1.0 + 2.0 * uv) * float2(ubo.aspectRatio, 1.0), -1.0)); - - // Basic color path - int id = 0; - float3 finalColor = renderScene(rayO, rayD, id); - - // Reflection - if (REFLECTIONS) - { - float reflectionStrength = REFLECTIONSTRENGTH; - for (int i = 0; i < RAYBOUNCES; i++) - { - float3 reflectionColor = renderScene(rayO, rayD, id); - finalColor = (1.0 - reflectionStrength) * finalColor + reflectionStrength * lerp(reflectionColor, finalColor, 1.0 - reflectionStrength); - reflectionStrength *= REFLECTIONFALLOFF; - } - } - - resultImage[int2(GlobalInvocationID.xy)] = float4(finalColor, 0.0); -} \ No newline at end of file diff --git a/shaders/slang/computeraytracing/texture.frag.spv b/shaders/slang/computeraytracing/texture.frag.spv deleted file mode 100644 index 2aab8ce9..00000000 Binary files a/shaders/slang/computeraytracing/texture.frag.spv and /dev/null differ diff --git a/shaders/slang/computeraytracing/texture.slang b/shaders/slang/computeraytracing/texture.slang deleted file mode 100644 index 0b126565..00000000 --- a/shaders/slang/computeraytracing/texture.slang +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - - struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f + -1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColor.Sample(float2(input.UV.x, 1.0 - input.UV.y)); -} \ No newline at end of file diff --git a/shaders/slang/computeraytracing/texture.vert.spv b/shaders/slang/computeraytracing/texture.vert.spv deleted file mode 100644 index 3ca929cc..00000000 Binary files a/shaders/slang/computeraytracing/texture.vert.spv and /dev/null differ diff --git a/shaders/slang/computeshader/edgedetect.comp.spv b/shaders/slang/computeshader/edgedetect.comp.spv deleted file mode 100644 index 5ee96ec4..00000000 Binary files a/shaders/slang/computeshader/edgedetect.comp.spv and /dev/null differ diff --git a/shaders/slang/computeshader/edgedetect.slang b/shaders/slang/computeshader/edgedetect.slang deleted file mode 100644 index ecbb5bf3..00000000 --- a/shaders/slang/computeshader/edgedetect.slang +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -import shared; - -[shader("compute")] -[numthreads(16, 16, 1)] -void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - float imageData[9]; - // Fetch neighbouring texels - int n = -1; - for (int i=-1; i<2; ++i) - { - for(int j=-1; j<2; ++j) - { - n++; - float3 rgb = inputImage[uint2(GlobalInvocationID.x + i, GlobalInvocationID.y + j)].rgb; - imageData[n] = (rgb.r + rgb.g + rgb.b) / 3.0; - } - } - - float kernel[9]; - kernel[0] = -1.0/8.0; kernel[1] = -1.0/8.0; kernel[2] = -1.0/8.0; - kernel[3] = -1.0/8.0; kernel[4] = 1.0; kernel[5] = -1.0/8.0; - kernel[6] = -1.0/8.0; kernel[7] = -1.0/8.0; kernel[8] = -1.0/8.0; - - float4 res = float4(conv(kernel, imageData, 0.1, 0.0).xxx, 1.0); - - resultImage[int2(GlobalInvocationID.xy)] = res; -} diff --git a/shaders/slang/computeshader/emboss.comp.spv b/shaders/slang/computeshader/emboss.comp.spv deleted file mode 100644 index 7f4bf29e..00000000 Binary files a/shaders/slang/computeshader/emboss.comp.spv and /dev/null differ diff --git a/shaders/slang/computeshader/emboss.slang b/shaders/slang/computeshader/emboss.slang deleted file mode 100644 index 6bd00f63..00000000 --- a/shaders/slang/computeshader/emboss.slang +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -import shared; - -[shader("compute")] -[numthreads(16, 16, 1)] -void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - float imageData[9]; - // Fetch neighbouring texels - int n = -1; - for (int i=-1; i<2; ++i) - { - for(int j=-1; j<2; ++j) - { - n++; - float3 rgb = inputImage[uint2(GlobalInvocationID.x + i, GlobalInvocationID.y + j)].rgb; - imageData[n] = (rgb.r + rgb.g + rgb.b) / 3.0; - } - } - - float kernel[9]; - kernel[0] = -1.0; kernel[1] = 0.0; kernel[2] = 0.0; - kernel[3] = 0.0; kernel[4] = -1.0; kernel[5] = 0.0; - kernel[6] = 0.0; kernel[7] = 0.0; kernel[8] = 2.0; - - float4 res = float4(conv(kernel, imageData, 1.0, 0.50).xxx, 1.0); - - resultImage[int2(GlobalInvocationID.xy)] = res; -} \ No newline at end of file diff --git a/shaders/slang/computeshader/shared.slang b/shaders/slang/computeshader/shared.slang deleted file mode 100644 index 54828404..00000000 --- a/shaders/slang/computeshader/shared.slang +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -module shared; - -public Texture2D inputImage; -public RWTexture2D resultImage; - -public float conv(in float kernel[9], in float data[9], in float denom, in float offset) -{ - float res = 0.0; - for (int i=0; i<9; ++i) - { - res += kernel[i] * data[i]; - } - return saturate(res/denom + offset); -} \ No newline at end of file diff --git a/shaders/slang/computeshader/sharpen.comp.spv b/shaders/slang/computeshader/sharpen.comp.spv deleted file mode 100644 index 255e0f80..00000000 Binary files a/shaders/slang/computeshader/sharpen.comp.spv and /dev/null differ diff --git a/shaders/slang/computeshader/sharpen.slang b/shaders/slang/computeshader/sharpen.slang deleted file mode 100644 index 0fa15f37..00000000 --- a/shaders/slang/computeshader/sharpen.slang +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -import shared; - -[shader("compute")] -[numthreads(16, 16, 1)] -void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID) -{ - float r[9]; - float g[9]; - float b[9]; - - // Fetch neighbouring texels - int n = -1; - for (int i=-1; i<2; ++i) - { - for(int j=-1; j<2; ++j) - { - n++; - float3 rgb = inputImage[uint2(GlobalInvocationID.x + i, GlobalInvocationID.y + j)].rgb; - r[n] = rgb.r; - g[n] = rgb.g; - b[n] = rgb.b; - } - } - - float kernel[9]; - kernel[0] = -1.0; kernel[1] = -1.0; kernel[2] = -1.0; - kernel[3] = -1.0; kernel[4] = 9.0; kernel[5] = -1.0; - kernel[6] = -1.0; kernel[7] = -1.0; kernel[8] = -1.0; - - float4 res = float4( - conv(kernel, r, 1.0, 0.0), - conv(kernel, g, 1.0, 0.0), - conv(kernel, b, 1.0, 0.0), - 1.0); - - resultImage[int2(GlobalInvocationID.xy)] = res; -} \ No newline at end of file diff --git a/shaders/slang/computeshader/texture.frag.spv b/shaders/slang/computeshader/texture.frag.spv deleted file mode 100644 index a08f8ff1..00000000 Binary files a/shaders/slang/computeshader/texture.frag.spv and /dev/null differ diff --git a/shaders/slang/computeshader/texture.slang b/shaders/slang/computeshader/texture.slang deleted file mode 100644 index dceb0669..00000000 --- a/shaders/slang/computeshader/texture.slang +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -ConstantBuffer ubo; - -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColor.Sample(input.UV); -} \ No newline at end of file diff --git a/shaders/slang/computeshader/texture.vert.spv b/shaders/slang/computeshader/texture.vert.spv deleted file mode 100644 index 4d759a9a..00000000 Binary files a/shaders/slang/computeshader/texture.vert.spv and /dev/null differ diff --git a/shaders/slang/conditionalrender/model.frag.spv b/shaders/slang/conditionalrender/model.frag.spv deleted file mode 100644 index 6cbde14f..00000000 Binary files a/shaders/slang/conditionalrender/model.frag.spv and /dev/null differ diff --git a/shaders/slang/conditionalrender/model.slang b/shaders/slang/conditionalrender/model.slang deleted file mode 100644 index fa4b8f9f..00000000 --- a/shaders/slang/conditionalrender/model.slang +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer ubo; - -struct Node -{ - float4x4 transform; -}; -[[vk::binding(0,1)]] ConstantBuffer node; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4 baseColorFactor) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = baseColorFactor.rgb; - float4 pos = float4(input.Pos, 1.0); - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, mul(node.transform, pos)))); - - output.Normal = mul((float4x3)mul(ubo.view, mul(ubo.model, node.transform)), input.Normal).xyz; - - float4 localpos = mul(ubo.view, mul(ubo.model, mul(node.transform, pos))); - float3 lightPos = float3(10.0f, -10.0f, 10.0f); - output.LightVec = lightPos.xyz - localpos.xyz; - output.ViewVec = -localpos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.1, 0.1, 0.1); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/conditionalrender/model.vert.spv b/shaders/slang/conditionalrender/model.vert.spv deleted file mode 100644 index a68320f1..00000000 Binary files a/shaders/slang/conditionalrender/model.vert.spv and /dev/null differ diff --git a/shaders/slang/conservativeraster/fullscreen.frag.spv b/shaders/slang/conservativeraster/fullscreen.frag.spv deleted file mode 100644 index a96badf3..00000000 Binary files a/shaders/slang/conservativeraster/fullscreen.frag.spv and /dev/null differ diff --git a/shaders/slang/conservativeraster/fullscreen.slang b/shaders/slang/conservativeraster/fullscreen.slang deleted file mode 100644 index d9705f60..00000000 --- a/shaders/slang/conservativeraster/fullscreen.slang +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColor.Sample(input.UV); -} \ No newline at end of file diff --git a/shaders/slang/conservativeraster/fullscreen.vert.spv b/shaders/slang/conservativeraster/fullscreen.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/conservativeraster/fullscreen.vert.spv and /dev/null differ diff --git a/shaders/slang/conservativeraster/triangle.frag.spv b/shaders/slang/conservativeraster/triangle.frag.spv deleted file mode 100644 index 81761f27..00000000 Binary files a/shaders/slang/conservativeraster/triangle.frag.spv and /dev/null differ diff --git a/shaders/slang/conservativeraster/triangle.slang b/shaders/slang/conservativeraster/triangle.slang deleted file mode 100644 index bc26b8f7..00000000 --- a/shaders/slang/conservativeraster/triangle.slang +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ -struct VSInput -{ - float3 Pos; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(input.Color, 1); -} \ No newline at end of file diff --git a/shaders/slang/conservativeraster/triangle.vert.spv b/shaders/slang/conservativeraster/triangle.vert.spv deleted file mode 100644 index 7a9b3bbe..00000000 Binary files a/shaders/slang/conservativeraster/triangle.vert.spv and /dev/null differ diff --git a/shaders/slang/conservativeraster/triangleoverlay.frag.spv b/shaders/slang/conservativeraster/triangleoverlay.frag.spv deleted file mode 100644 index 5cbccf9c..00000000 Binary files a/shaders/slang/conservativeraster/triangleoverlay.frag.spv and /dev/null differ diff --git a/shaders/slang/conservativeraster/triangleoverlay.slang b/shaders/slang/conservativeraster/triangleoverlay.slang deleted file mode 100644 index 6915ce36..00000000 --- a/shaders/slang/conservativeraster/triangleoverlay.slang +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -[shader("fragment")] -float4 fragmentMain() -{ - return float4(1.0, 1.0, 1.0, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/debugprintf/toon.frag.spv b/shaders/slang/debugprintf/toon.frag.spv deleted file mode 100644 index d2367292..00000000 Binary files a/shaders/slang/debugprintf/toon.frag.spv and /dev/null differ diff --git a/shaders/slang/debugprintf/toon.slang b/shaders/slang/debugprintf/toon.slang deleted file mode 100644 index 1c638bcb..00000000 --- a/shaders/slang/debugprintf/toon.slang +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - // Output the vertex position using debug printf - printf("Position = %v4f", pos); - - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - float3 lPos = mul((float4x3)ubo.model, ubo.lightPos.xyz).xyz; - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Desaturate color - float3 color = float3(lerp(input.Color, dot(float3(0.2126, 0.7152, 0.0722), input.Color).xxx, 0.65)); - - // High ambient colors because mesh materials are pretty dark - float3 ambient = color * float3(1.0, 1.0, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - - float intensity = dot(N, L); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - return float4(input.Color * 3.0 * shade, 1); -} \ No newline at end of file diff --git a/shaders/slang/debugprintf/toon.vert.spv b/shaders/slang/debugprintf/toon.vert.spv deleted file mode 100644 index dda273ae..00000000 Binary files a/shaders/slang/debugprintf/toon.vert.spv and /dev/null differ diff --git a/shaders/slang/debugutils/colorpass.frag.spv b/shaders/slang/debugutils/colorpass.frag.spv deleted file mode 100644 index 81761f27..00000000 Binary files a/shaders/slang/debugutils/colorpass.frag.spv and /dev/null differ diff --git a/shaders/slang/debugutils/colorpass.slang b/shaders/slang/debugutils/colorpass.slang deleted file mode 100644 index 7061a628..00000000 --- a/shaders/slang/debugutils/colorpass.slang +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, input.Pos)); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/debugutils/colorpass.vert.spv b/shaders/slang/debugutils/colorpass.vert.spv deleted file mode 100644 index d74fcd9e..00000000 Binary files a/shaders/slang/debugutils/colorpass.vert.spv and /dev/null differ diff --git a/shaders/slang/debugutils/postprocess.frag.spv b/shaders/slang/debugutils/postprocess.frag.spv deleted file mode 100644 index 59b020b2..00000000 Binary files a/shaders/slang/debugutils/postprocess.frag.spv and /dev/null differ diff --git a/shaders/slang/debugutils/postprocess.slang b/shaders/slang/debugutils/postprocess.slang deleted file mode 100644 index a1bce2f7..00000000 --- a/shaders/slang/debugutils/postprocess.slang +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -[[vk::binding(1, 0)]] Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * float2(2.0f, 2.0f) + float2(-1.0f, -1.0f), 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Single pass gauss blur - - const float2 texOffset = float2(0.01, 0.01); - - float2 tc0 = input.UV + float2(-texOffset.x, -texOffset.y); - float2 tc1 = input.UV + float2( 0.0, -texOffset.y); - float2 tc2 = input.UV + float2(+texOffset.x, -texOffset.y); - float2 tc3 = input.UV + float2(-texOffset.x, 0.0); - float2 tc4 = input.UV + float2( 0.0, 0.0); - float2 tc5 = input.UV + float2(+texOffset.x, 0.0); - float2 tc6 = input.UV + float2(-texOffset.x, +texOffset.y); - float2 tc7 = input.UV + float2( 0.0, +texOffset.y); - float2 tc8 = input.UV + float2(+texOffset.x, +texOffset.y); - - float4 col0 = samplerColor.Sample(tc0); - float4 col1 = samplerColor.Sample(tc1); - float4 col2 = samplerColor.Sample(tc2); - float4 col3 = samplerColor.Sample(tc3); - float4 col4 = samplerColor.Sample(tc4); - float4 col5 = samplerColor.Sample(tc5); - float4 col6 = samplerColor.Sample(tc6); - float4 col7 = samplerColor.Sample(tc7); - float4 col8 = samplerColor.Sample(tc8); - - float4 sum = (1.0 * col0 + 2.0 * col1 + 1.0 * col2 + - 2.0 * col3 + 4.0 * col4 + 2.0 * col5 + - 1.0 * col6 + 2.0 * col7 + 1.0 * col8) / 16.0; - return float4(sum.rgb, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/debugutils/postprocess.vert.spv b/shaders/slang/debugutils/postprocess.vert.spv deleted file mode 100644 index f1935d3d..00000000 Binary files a/shaders/slang/debugutils/postprocess.vert.spv and /dev/null differ diff --git a/shaders/slang/debugutils/toon.frag.spv b/shaders/slang/debugutils/toon.frag.spv deleted file mode 100644 index 669f325d..00000000 Binary files a/shaders/slang/debugutils/toon.frag.spv and /dev/null differ diff --git a/shaders/slang/debugutils/toon.slang b/shaders/slang/debugutils/toon.slang deleted file mode 100644 index 8d69bee0..00000000 --- a/shaders/slang/debugutils/toon.slang +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - float3 lPos = mul((float4x3)ubo.model, ubo.lightPos.xyz).xyz; - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Desaturate color - float3 color = float3(lerp(input.Color, dot(float3(0.2126,0.7152,0.0722), input.Color).xxx, 0.65)); - - // High ambient colors because mesh materials are pretty dark - float3 ambient = color * float3(1.0, 1.0, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - - float intensity = dot(N,L); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - return float4(input.Color * 3.0 * shade, 1); -} \ No newline at end of file diff --git a/shaders/slang/debugutils/toon.vert.spv b/shaders/slang/debugutils/toon.vert.spv deleted file mode 100644 index 0dd9a7e0..00000000 Binary files a/shaders/slang/debugutils/toon.vert.spv and /dev/null differ diff --git a/shaders/slang/deferred/deferred.frag.spv b/shaders/slang/deferred/deferred.frag.spv deleted file mode 100644 index 1ca9d175..00000000 Binary files a/shaders/slang/deferred/deferred.frag.spv and /dev/null differ diff --git a/shaders/slang/deferred/deferred.slang b/shaders/slang/deferred/deferred.slang deleted file mode 100644 index e02ef0d5..00000000 --- a/shaders/slang/deferred/deferred.slang +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -[[vk::binding(1, 0)]] Sampler2D samplerposition; -[[vk::binding(2, 0)]] Sampler2D samplerNormal; -[[vk::binding(3, 0)]] Sampler2D samplerAlbedo; - -struct Light { - float4 position; - float3 color; - float radius; -}; - -struct UBO -{ - Light lights[6]; - float4 viewPos; - int displayDebugTarget; -}; -[[vk::binding(4, 0)]] ConstantBuffer ubo; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Get G-Buffer values - float3 fragPos = samplerposition.Sample(input.UV).rgb; - float3 normal = samplerNormal.Sample(input.UV).rgb; - float4 albedo = samplerAlbedo.Sample(input.UV); - - float3 fragcolor; - - // Debug display - if (ubo.displayDebugTarget > 0) { - switch (ubo.displayDebugTarget) { - case 1: - fragcolor.rgb = fragPos; - break; - case 2: - fragcolor.rgb = normal; - break; - case 3: - fragcolor.rgb = albedo.rgb; - break; - case 4: - fragcolor.rgb = albedo.aaa; - break; - } - return float4(fragcolor, 1.0); - } - - #define lightCount 6 - #define ambient 0.0 - - // Ambient part - fragcolor = albedo.rgb * ambient; - - for(int i = 0; i < lightCount; ++i) - { - // Vector to light - float3 L = ubo.lights[i].position.xyz - fragPos; - // Distance from light to fragment position - float dist = length(L); - - // Viewer to fragment - float3 V = ubo.viewPos.xyz - fragPos; - V = normalize(V); - - //if(dist < ubo.lights[i].radius) - { - // Light to fragment - L = normalize(L); - - // Attenuation - float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0); - - // Diffuse part - float3 N = normalize(normal); - float NdotL = max(0.0, dot(N, L)); - float3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten; - - // Specular part - // Specular map values are stored in alpha of albedo mrt - float3 R = reflect(-L, N); - float NdotR = max(0.0, dot(R, V)); - float3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 16.0) * atten; - - fragcolor += diff + spec; - } - } - - return float4(fragcolor, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/deferred/deferred.vert.spv b/shaders/slang/deferred/deferred.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/deferred/deferred.vert.spv and /dev/null differ diff --git a/shaders/slang/deferred/mrt.frag.spv b/shaders/slang/deferred/mrt.frag.spv deleted file mode 100644 index f3ebda26..00000000 Binary files a/shaders/slang/deferred/mrt.frag.spv and /dev/null differ diff --git a/shaders/slang/deferred/mrt.slang b/shaders/slang/deferred/mrt.slang deleted file mode 100644 index 8df7a701..00000000 --- a/shaders/slang/deferred/mrt.slang +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -[[vk::binding(1, 0)]] Sampler2D samplerColor; -[[vk::binding(2, 0)]] Sampler2D samplerNormalMap; - -struct VSInput -{ - float4 Pos; - float2 UV; - float3 Color; - float3 Normal; - float3 Tangent; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; - float3 Color; - float3 WorldPos; - float3 Tangent; -}; - -struct FSOutput -{ - float4 Position; - float4 Normal; - float4 Albedo; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float4 instancePos[3]; -}; -[[vk::binding(0, 0)]] ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uint InstanceIndex: SV_InstanceID) -{ - VSOutput output; - float4 tmpPos = input.Pos + ubo.instancePos[InstanceIndex]; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, tmpPos))); - - output.UV = input.UV; - - // Vertex position in world space - output.WorldPos = mul(ubo.model, tmpPos).xyz; - - // Normal in world space - output.Normal = normalize(input.Normal); - output.Tangent = normalize(input.Tangent); - - // Currently just vertex color - output.Color = input.Color; - return output; -} - -[shader("fragment")] -FSOutput fragmentMain(VSOutput input) -{ - FSOutput output; - output.Position = float4(input.WorldPos, 1.0); - - // Calculate normal in tangent space - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent); - float3 B = cross(N, T); - float3x3 TBN = float3x3(T, B, N); - float3 tnorm = mul(normalize(samplerNormalMap.Sample(input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - output.Normal = float4(tnorm, 1.0); - - output.Albedo = samplerColor.Sample(input.UV); - return output; -} \ No newline at end of file diff --git a/shaders/slang/deferred/mrt.vert.spv b/shaders/slang/deferred/mrt.vert.spv deleted file mode 100644 index 92230a26..00000000 Binary files a/shaders/slang/deferred/mrt.vert.spv and /dev/null differ diff --git a/shaders/slang/deferredmultisampling/deferred.frag.spv b/shaders/slang/deferredmultisampling/deferred.frag.spv deleted file mode 100644 index fa6ba70a..00000000 Binary files a/shaders/slang/deferredmultisampling/deferred.frag.spv and /dev/null differ diff --git a/shaders/slang/deferredmultisampling/deferred.slang b/shaders/slang/deferredmultisampling/deferred.slang deleted file mode 100644 index 81d3b3bc..00000000 --- a/shaders/slang/deferredmultisampling/deferred.slang +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -[[vk::binding(1, 0)]] Texture2DMS samplerPosition; -[[vk::binding(2, 0)]] Texture2DMS samplerNormal; -[[vk::binding(3, 0)]] Texture2DMS samplerAlbedo; - -struct Light { - float4 position; - float3 color; - float radius; -}; - -struct UBO -{ - Light lights[6]; - float4 viewPos; - int displayDebugTarget; -}; -[[vk::binding(4, 0)]] ConstantBuffer ubo; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -[[SpecializationConstant]] const int NUM_SAMPLES = 8; -#define NUM_LIGHTS 6 - -// Manual resolve for MSAA samples -float4 resolve(Texture2DMS tex, int2 uv) -{ - float4 result = float4(0.0, 0.0, 0.0, 0.0); - for (int i = 0; i < NUM_SAMPLES; i++) - { - uint status = 0; - float4 val = tex.Load(uv, i, int2(0, 0), status); - result += val; - } - // Average resolved samples - return result / float(NUM_SAMPLES); -} - -float3 calculateLighting(float3 pos, float3 normal, float4 albedo) -{ - float3 result = float3(0.0, 0.0, 0.0); - - for (int i = 0; i < NUM_LIGHTS; ++i) - { - // Vector to light - float3 L = ubo.lights[i].position.xyz - pos; - // Distance from light to fragment position - float dist = length(L); - - // Viewer to fragment - float3 V = ubo.viewPos.xyz - pos; - V = normalize(V); - - // Light to fragment - L = normalize(L); - - // Attenuation - float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0); - - // Diffuse part - float3 N = normalize(normal); - float NdotL = max(0.0, dot(N, L)); - float3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten; - - // Specular part - float3 R = reflect(-L, N); - float NdotR = max(0.0, dot(R, V)); - float3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 8.0) * atten; - - result += diff + spec; - } - return result; -} - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - int2 attDim; int sampleCount; - samplerPosition.GetDimensions(attDim.x, attDim.y, sampleCount); - int2 UV = int2(input.UV * attDim); - - float3 fragColor; - uint status = 0; - - // Debug display - if (ubo.displayDebugTarget > 0) { - switch (ubo.displayDebugTarget) { - case 1: - fragColor.rgb = samplerPosition.Load(UV, 0, int2(0, 0), status).rgb; - break; - case 2: - fragColor.rgb = samplerNormal.Load(UV, 0, int2(0, 0), status).rgb; - break; - case 3: - fragColor.rgb = samplerAlbedo.Load(UV, 0, int2(0, 0), status).rgb; - break; - case 4: - fragColor.rgb = samplerAlbedo.Load(UV, 0, int2(0, 0), status).aaa; - break; - } - return float4(fragColor, 1.0); - } - -#define ambient 0.15 - - // Ambient part - float4 alb = resolve(samplerAlbedo, UV); - fragColor = float3(0.0, 0.0, 0.0); - - // Calualte lighting for every MSAA sample - for (int i = 0; i < NUM_SAMPLES; i++) - { - float3 pos = samplerPosition.Load(UV, i, int2(0, 0), status).rgb; - float3 normal = samplerNormal.Load(UV, i, int2(0, 0), status).rgb; - float4 albedo = samplerAlbedo.Load(UV, i, int2(0, 0), status); - fragColor += calculateLighting(pos, normal, albedo); - } - - fragColor = (alb.rgb * ambient) + fragColor / float(NUM_SAMPLES); - - return float4(fragColor, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/deferredmultisampling/deferred.vert.spv b/shaders/slang/deferredmultisampling/deferred.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/deferredmultisampling/deferred.vert.spv and /dev/null differ diff --git a/shaders/slang/deferredmultisampling/mrt.frag.spv b/shaders/slang/deferredmultisampling/mrt.frag.spv deleted file mode 100644 index f3ebda26..00000000 Binary files a/shaders/slang/deferredmultisampling/mrt.frag.spv and /dev/null differ diff --git a/shaders/slang/deferredmultisampling/mrt.slang b/shaders/slang/deferredmultisampling/mrt.slang deleted file mode 100644 index 146c4fd2..00000000 --- a/shaders/slang/deferredmultisampling/mrt.slang +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float2 UV; - float3 Color; - float3 Normal; - float3 Tangent; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; - float3 Color; - float3 WorldPos; - float3 Tangent; -}; - -struct FSOutput -{ - float4 Position; - float4 Normal; - float4 Albedo; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float4 instancePos[3]; -}; -ConstantBuffer ubo; - -Sampler2D samplerColor; -Sampler2D samplerNormalMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uint InstanceIndex: SV_InstanceID) -{ - VSOutput output; - float4 tmpPos = input.Pos + ubo.instancePos[InstanceIndex]; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, tmpPos))); - - output.UV = input.UV; - - // Vertex position in world space - output.WorldPos = mul(ubo.model, tmpPos).xyz; - - // Normal in world space - output.Normal = normalize(input.Normal); - output.Tangent = normalize(input.Tangent); - - // Currently just vertex color - output.Color = input.Color; - return output; -} - -[shader("fragment")] -FSOutput fragmentMain(VSOutput input) -{ - FSOutput output; - output.Position = float4(input.WorldPos, 1.0); - - // Calculate normal in tangent space - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent); - float3 B = cross(N, T); - float3x3 TBN = float3x3(T, B, N); - float3 tnorm = mul(normalize(samplerNormalMap.Sample(input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - output.Normal = float4(tnorm, 1.0); - - output.Albedo = samplerColor.Sample(input.UV); - return output; -} \ No newline at end of file diff --git a/shaders/slang/deferredmultisampling/mrt.vert.spv b/shaders/slang/deferredmultisampling/mrt.vert.spv deleted file mode 100644 index 92230a26..00000000 Binary files a/shaders/slang/deferredmultisampling/mrt.vert.spv and /dev/null differ diff --git a/shaders/slang/deferredshadows/deferred.frag.spv b/shaders/slang/deferredshadows/deferred.frag.spv deleted file mode 100644 index 0ee9c595..00000000 Binary files a/shaders/slang/deferredshadows/deferred.frag.spv and /dev/null differ diff --git a/shaders/slang/deferredshadows/deferred.slang b/shaders/slang/deferredshadows/deferred.slang deleted file mode 100644 index f7759227..00000000 --- a/shaders/slang/deferredshadows/deferred.slang +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2020 Google LLC - -#define LIGHT_COUNT 3 -#define SHADOW_FACTOR 0.25 -#define AMBIENT_LIGHT 0.1 -#define USE_PCF - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -[[vk::binding(1, 0)]] Sampler2D samplerPosition; -[[vk::binding(2, 0)]] Sampler2D samplerNormal; -[[vk::binding(3, 0)]] Sampler2D samplerAlbedo; - -struct Light -{ - float4 position; - float4 target; - float4 color; - float4x4 viewMatrix; -}; - -struct UBO -{ - float4 viewPos; - Light lights[LIGHT_COUNT]; - int useShadows; - int displayDebugTarget; -}; -[[vk::binding(4, 0)]] ConstantBuffer ubo; - -// Depth from the light's point of view -// layout (binding = 5) uniform sampler2DShadow samplerShadowMap; -[[vk::binding(5, 0)]] Sampler2DArray samplerShadowMap; - -float textureProj(float4 P, float layer, float2 offset) -{ - float shadow = 1.0; - float4 shadowCoord = P / P.w; - shadowCoord.xy = shadowCoord.xy * 0.5 + 0.5; - - if (shadowCoord.z > -1.0 && shadowCoord.z < 1.0) - { - float dist = samplerShadowMap.Sample(float3(shadowCoord.xy + offset, layer)).r; - if (shadowCoord.w > 0.0 && dist < shadowCoord.z) - { - shadow = SHADOW_FACTOR; - } - } - return shadow; -} - -float filterPCF(float4 sc, float layer) -{ - int2 texDim; int elements; int levels; - samplerShadowMap.GetDimensions(0, texDim.x, texDim.y, elements, levels); - float scale = 1.5; - float dx = scale * 1.0 / float(texDim.x); - float dy = scale * 1.0 / float(texDim.y); - - float shadowFactor = 0.0; - int count = 0; - int range = 1; - - for (int x = -range; x <= range; x++) - { - for (int y = -range; y <= range; y++) - { - shadowFactor += textureProj(sc, layer, float2(dx*x, dy*y)); - count++; - } - - } - return shadowFactor / count; -} - -float3 shadow(float3 fragcolor, float3 fragPos) -{ - for (int i = 0; i < LIGHT_COUNT; ++i) - { - float4 shadowClip = mul(ubo.lights[i].viewMatrix, float4(fragPos.xyz, 1.0)); - - float shadowFactor; - #ifdef USE_PCF - shadowFactor= filterPCF(shadowClip, i); - #else - shadowFactor = textureProj(shadowClip, i, float2(0.0, 0.0)); - #endif - - fragcolor *= shadowFactor; - } - return fragcolor; -} - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Get G-Buffer values - float3 fragPos = samplerPosition.Sample(input.UV).rgb; - float3 normal = samplerNormal.Sample(input.UV).rgb; - float4 albedo = samplerAlbedo.Sample(input.UV); - - float3 fragcolor; - - // Debug display - if (ubo.displayDebugTarget > 0) { - switch (ubo.displayDebugTarget) { - case 1: - fragcolor.rgb = shadow(float3(1.0, 1.0, 1.0), fragPos); - break; - case 2: - fragcolor.rgb = fragPos; - break; - case 3: - fragcolor.rgb = normal; - break; - case 4: - fragcolor.rgb = albedo.rgb; - break; - case 5: - fragcolor.rgb = albedo.aaa; - break; - } - return float4(fragcolor, 1.0); - } - - // Ambient part - fragcolor = albedo.rgb * AMBIENT_LIGHT; - - float3 N = normalize(normal); - - for(int i = 0; i < LIGHT_COUNT; ++i) - { - // Vector to light - float3 L = ubo.lights[i].position.xyz - fragPos; - // Distance from light to fragment position - float dist = length(L); - L = normalize(L); - - // Viewer to fragment - float3 V = ubo.viewPos.xyz - fragPos; - V = normalize(V); - - float lightCosInnerAngle = cos(radians(15.0)); - float lightCosOuterAngle = cos(radians(25.0)); - float lightRange = 100.0; - - // Direction vector from source to target - float3 dir = normalize(ubo.lights[i].position.xyz - ubo.lights[i].target.xyz); - - // Dual cone spot light with smooth transition between inner and outer angle - float cosDir = dot(L, dir); - float spotEffect = smoothstep(lightCosOuterAngle, lightCosInnerAngle, cosDir); - float heightAttenuation = smoothstep(lightRange, 0.0f, dist); - - // Diffuse lighting - float NdotL = max(0.0, dot(N, L)); - float3 diff = NdotL.xxx; - - // Specular lighting - float3 R = reflect(-L, N); - float NdotR = max(0.0, dot(R, V)); - float3 spec = (pow(NdotR, 16.0) * albedo.a * 2.5).xxx; - - fragcolor += float3((diff + spec) * spotEffect * heightAttenuation) * ubo.lights[i].color.rgb * albedo.rgb; - } - - // Shadow calculations in a separate pass - if (ubo.useShadows > 0) - { - fragcolor = shadow(fragcolor, fragPos); - } - - return float4(fragcolor, 1); -} \ No newline at end of file diff --git a/shaders/slang/deferredshadows/deferred.vert.spv b/shaders/slang/deferredshadows/deferred.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/deferredshadows/deferred.vert.spv and /dev/null differ diff --git a/shaders/slang/deferredshadows/mrt.frag.spv b/shaders/slang/deferredshadows/mrt.frag.spv deleted file mode 100644 index f3ebda26..00000000 Binary files a/shaders/slang/deferredshadows/mrt.frag.spv and /dev/null differ diff --git a/shaders/slang/deferredshadows/mrt.slang b/shaders/slang/deferredshadows/mrt.slang deleted file mode 100644 index 53b42587..00000000 --- a/shaders/slang/deferredshadows/mrt.slang +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float2 UV; - float3 Color; - float3 Normal; - float3 Tangent; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; - float3 Color; - float3 WorldPos; - float3 Tangent; -}; - -struct FSOutput -{ - float4 Position : SV_TARGET0; - float4 Normal : SV_TARGET1; - float4 Albedo : SV_TARGET2; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float4 instancePos[3]; -}; -ConstantBuffer ubo; - -Sampler2D samplerColor; -Sampler2D samplerNormalMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uint InstanceIndex: SV_InstanceID) -{ - VSOutput output; - float4 tmpPos = input.Pos + ubo.instancePos[InstanceIndex]; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, tmpPos))); - - output.UV = input.UV; - - // Vertex position in world space - output.WorldPos = mul(ubo.model, tmpPos).xyz; - - // Normal in world space - output.Normal = normalize(input.Normal); - output.Tangent = normalize(input.Tangent); - - // Currently just vertex color - output.Color = input.Color; - return output; -} - -[shader("fragment")] -FSOutput fragmentMain(VSOutput input) -{ - FSOutput output; - output.Position = float4(input.WorldPos, 1.0); - - // Calculate normal in tangent space - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent); - float3 B = cross(N, T); - float3x3 TBN = float3x3(T, B, N); - float3 tnorm = mul(normalize(samplerNormalMap.Sample(input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - output.Normal = float4(tnorm, 1.0); - - output.Albedo = samplerColor.Sample(input.UV); - return output; -} \ No newline at end of file diff --git a/shaders/slang/deferredshadows/mrt.vert.spv b/shaders/slang/deferredshadows/mrt.vert.spv deleted file mode 100644 index 92230a26..00000000 Binary files a/shaders/slang/deferredshadows/mrt.vert.spv and /dev/null differ diff --git a/shaders/slang/deferredshadows/shadow.geom.spv b/shaders/slang/deferredshadows/shadow.geom.spv deleted file mode 100644 index 2d99b8e5..00000000 Binary files a/shaders/slang/deferredshadows/shadow.geom.spv and /dev/null differ diff --git a/shaders/slang/deferredshadows/shadow.slang b/shaders/slang/deferredshadows/shadow.slang deleted file mode 100644 index 68ada4a9..00000000 --- a/shaders/slang/deferredshadows/shadow.slang +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#define LIGHT_COUNT 3 - -struct VSInput -{ - float4 Pos; -} - -struct VSOutput -{ - float4 Pos : SV_POSITION; - int InstanceIndex; -}; - -struct GSOutput -{ - float4 Pos : SV_POSITION; - int Layer : SV_RenderTargetArrayIndex; -}; - -struct UBO -{ - float4x4 mvp[LIGHT_COUNT]; - float4 instancePos[3]; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uint InstanceIndex: SV_InstanceID) -{ - VSOutput output; - output.InstanceIndex = InstanceIndex; - output.Pos = input.Pos; - return output; -} - -[shader("geometry")] -[maxvertexcount(3)] -[instance(3)] -void geometryMain(triangle VSOutput input[3], uint InvocationID : SV_GSInstanceID, inout TriangleStream outStream) -{ - float4 instancedPos = ubo.instancePos[input[0].InstanceIndex]; - for (int i = 0; i < 3; i++) - { - float4 tmpPos = input[i].Pos + instancedPos; - GSOutput output; - output.Pos = mul(ubo.mvp[InvocationID], tmpPos); - output.Layer = InvocationID; - outStream.Append( output ); - } - outStream.RestartStrip(); -} \ No newline at end of file diff --git a/shaders/slang/deferredshadows/shadow.vert.spv b/shaders/slang/deferredshadows/shadow.vert.spv deleted file mode 100644 index eed17f3e..00000000 Binary files a/shaders/slang/deferredshadows/shadow.vert.spv and /dev/null differ diff --git a/shaders/slang/descriptorbuffer/cube.frag.spv b/shaders/slang/descriptorbuffer/cube.frag.spv deleted file mode 100644 index 1e7ca802..00000000 Binary files a/shaders/slang/descriptorbuffer/cube.frag.spv and /dev/null differ diff --git a/shaders/slang/descriptorbuffer/cube.slang b/shaders/slang/descriptorbuffer/cube.slang deleted file mode 100644 index 7d6e3ad3..00000000 --- a/shaders/slang/descriptorbuffer/cube.slang +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; -}; - -struct UBOCamera { - float4x4 projection; - float4x4 view; -}; -ConstantBuffer uboCamera; - -struct UBOModel { - float4x4 local; -}; -[[vk::binding(0, 1)]] ConstantBuffer uboModel; - -[[vk::binding(0, 2)]] Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(uboCamera.projection, mul(uboCamera.view, mul(uboModel.local, float4(input.Pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/descriptorbuffer/cube.vert.spv b/shaders/slang/descriptorbuffer/cube.vert.spv deleted file mode 100644 index bbc25b87..00000000 Binary files a/shaders/slang/descriptorbuffer/cube.vert.spv and /dev/null differ diff --git a/shaders/slang/descriptorindexing/descriptorindexing.frag.spv b/shaders/slang/descriptorindexing/descriptorindexing.frag.spv deleted file mode 100644 index 5f2ad97c..00000000 Binary files a/shaders/slang/descriptorindexing/descriptorindexing.frag.spv and /dev/null differ diff --git a/shaders/slang/descriptorindexing/descriptorindexing.slang b/shaders/slang/descriptorindexing/descriptorindexing.slang deleted file mode 100644 index 5c25ea88..00000000 --- a/shaders/slang/descriptorindexing/descriptorindexing.slang +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos : POSITION0; - float2 UV; - int TextureIndex; -}; - -struct Matrices { - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer matrices; -Sampler2D textures[]; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - int TextureIndex; - float2 UV; -}; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - output.TextureIndex = input.TextureIndex; - output.Pos = mul(matrices.projection, mul(matrices.view, mul(matrices.model, float4(input.Pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return textures[NonUniformResourceIndex(input.TextureIndex)].Sample(input.UV); -} \ No newline at end of file diff --git a/shaders/slang/descriptorindexing/descriptorindexing.vert.spv b/shaders/slang/descriptorindexing/descriptorindexing.vert.spv deleted file mode 100644 index 1e80db21..00000000 Binary files a/shaders/slang/descriptorindexing/descriptorindexing.vert.spv and /dev/null differ diff --git a/shaders/slang/descriptorsets/cube.frag.spv b/shaders/slang/descriptorsets/cube.frag.spv deleted file mode 100644 index 2aaac7d7..00000000 Binary files a/shaders/slang/descriptorsets/cube.frag.spv and /dev/null differ diff --git a/shaders/slang/descriptorsets/cube.slang b/shaders/slang/descriptorsets/cube.slang deleted file mode 100644 index 8a8b0ec9..00000000 --- a/shaders/slang/descriptorsets/cube.slang +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; -}; - -// Slang auto generates bindings by order of descriptors -// So the UBO is bound to slot 0, the sampler to slot 1 -// due to their order in the shader - -struct UBOMatrices { - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer uboMatrices; - -Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(uboMatrices.projection, mul(uboMatrices.view, mul(uboMatrices.model, float4(input.Pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/descriptorsets/cube.vert.spv b/shaders/slang/descriptorsets/cube.vert.spv deleted file mode 100644 index 398cf230..00000000 Binary files a/shaders/slang/descriptorsets/cube.vert.spv and /dev/null differ diff --git a/shaders/slang/displacement/base.frag.spv b/shaders/slang/displacement/base.frag.spv deleted file mode 100644 index 128751c6..00000000 Binary files a/shaders/slang/displacement/base.frag.spv and /dev/null differ diff --git a/shaders/slang/displacement/base.vert.spv b/shaders/slang/displacement/base.vert.spv deleted file mode 100644 index b50c5a1e..00000000 Binary files a/shaders/slang/displacement/base.vert.spv and /dev/null differ diff --git a/shaders/slang/displacement/displacement.slang b/shaders/slang/displacement/displacement.slang deleted file mode 100644 index ec8f171c..00000000 --- a/shaders/slang/displacement/displacement.slang +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; -}; - -struct HSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; -}; - -struct DSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; - float3 EyePos; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; - float tessAlpha; - float tessStrength; - float tessLevel; -}; -ConstantBuffer ubo; - -Sampler2D samplerColorAndDisplacementMap; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner[2] : SV_InsideTessFactor; -}; - -ConstantsHSOutput ConstantsHS() -{ - ConstantsHSOutput output; - output.TessLevelInner[0] = ubo.tessLevel; - output.TessLevelInner[1] = ubo.tessLevel; - output.TessLevelOuter[0] = ubo.tessLevel; - output.TessLevelOuter[1] = ubo.tessLevel; - output.TessLevelOuter[2] = ubo.tessLevel; - return output; -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = float4(input.Pos.xyz, 1.0); - output.UV = input.UV; - output.Normal = input.Normal; - return output; -} - -[shader("hull")] -[domain("tri")] -[partitioning("integer")] -[outputtopology("triangle_cw")] -[outputcontrolpoints(3)] -[patchconstantfunc("ConstantsHS")] -[maxtessfactor(20.0f)] -HSOutput hullMain(InputPatch patch, uint InvocationID: SV_OutputControlPointID) -{ - HSOutput output; - output.Pos = patch[InvocationID].Pos; - output.Normal = patch[InvocationID].Normal; - output.UV = patch[InvocationID].UV; - return output; -} - -[shader("domain")] -[domain("tri")] -DSOutput domainMain(ConstantsHSOutput input, float3 TessCoord: SV_DomainLocation, const OutputPatch patch) -{ - DSOutput output; - output.Pos = (TessCoord.x * patch[0].Pos) + (TessCoord.y * patch[1].Pos) + (TessCoord.z * patch[2].Pos); - output.UV = (TessCoord.x * patch[0].UV) + (TessCoord.y * patch[1].UV) + (TessCoord.z * patch[2].UV); - output.Normal = TessCoord.x * patch[0].Normal + TessCoord.y * patch[1].Normal + TessCoord.z * patch[2].Normal; - output.Pos.xyz += normalize(output.Normal) * (max(samplerColorAndDisplacementMap.SampleLevel(output.UV.xy, 0).a, 0.0) * ubo.tessStrength); - output.EyePos = output.Pos.xyz; - output.LightVec = normalize(ubo.lightPos.xyz - output.EyePos); - output.Pos = mul(ubo.projection, mul(ubo.model, output.Pos)); - return output; -} - -[shader("fragment")] -float4 fragmentMain(DSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(float3(1.0, 1.0, 1.0)); - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - float4 IAmbient = float4(0.0, 0.0, 0.0, 1.0); - float4 IDiffuse = float4(1.0, 1.0, 1.0, 1.0) * max(dot(input.Normal, input.LightVec), 0.0); - return float4((IAmbient + IDiffuse) * float4(samplerColorAndDisplacementMap.Sample(input.UV).rgb, 1.0)); -} diff --git a/shaders/slang/displacement/displacement.tesc.spv b/shaders/slang/displacement/displacement.tesc.spv deleted file mode 100644 index 593d7b18..00000000 Binary files a/shaders/slang/displacement/displacement.tesc.spv and /dev/null differ diff --git a/shaders/slang/displacement/displacement.tese.spv b/shaders/slang/displacement/displacement.tese.spv deleted file mode 100644 index 3c4bfd59..00000000 Binary files a/shaders/slang/displacement/displacement.tese.spv and /dev/null differ diff --git a/shaders/slang/distancefieldfonts/bitmap.frag.spv b/shaders/slang/distancefieldfonts/bitmap.frag.spv deleted file mode 100644 index da5638c3..00000000 Binary files a/shaders/slang/distancefieldfonts/bitmap.frag.spv and /dev/null differ diff --git a/shaders/slang/distancefieldfonts/bitmap.slang b/shaders/slang/distancefieldfonts/bitmap.slang deleted file mode 100644 index 59849e00..00000000 --- a/shaders/slang/distancefieldfonts/bitmap.slang +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -ConstantBuffer ubo; -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColor.Sample(input.UV).aaaa; -} \ No newline at end of file diff --git a/shaders/slang/distancefieldfonts/bitmap.vert.spv b/shaders/slang/distancefieldfonts/bitmap.vert.spv deleted file mode 100644 index 4d759a9a..00000000 Binary files a/shaders/slang/distancefieldfonts/bitmap.vert.spv and /dev/null differ diff --git a/shaders/slang/distancefieldfonts/sdf.frag.spv b/shaders/slang/distancefieldfonts/sdf.frag.spv deleted file mode 100644 index 663a9d57..00000000 Binary files a/shaders/slang/distancefieldfonts/sdf.frag.spv and /dev/null differ diff --git a/shaders/slang/distancefieldfonts/sdf.slang b/shaders/slang/distancefieldfonts/sdf.slang deleted file mode 100644 index 2d3bb235..00000000 --- a/shaders/slang/distancefieldfonts/sdf.slang +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; -}; - - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 outlineColor; - float outlineWidth; - float outline; -}; -ConstantBuffer ubo; -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float dist = samplerColor.Sample(input.UV).a; - float smoothWidth = fwidth(dist); - float alpha = smoothstep(0.5 - smoothWidth, 0.5 + smoothWidth, dist); - float3 rgb = alpha.xxx; - - if (ubo.outline > 0.0) - { - float w = 1.0 - ubo.outlineWidth; - alpha = smoothstep(w - smoothWidth, w + smoothWidth, dist); - rgb += lerp(alpha.xxx, ubo.outlineColor.rgb, alpha); - } - - return float4(rgb, alpha); -} \ No newline at end of file diff --git a/shaders/slang/distancefieldfonts/sdf.vert.spv b/shaders/slang/distancefieldfonts/sdf.vert.spv deleted file mode 100644 index 931059c7..00000000 Binary files a/shaders/slang/distancefieldfonts/sdf.vert.spv and /dev/null differ diff --git a/shaders/slang/dynamicrendering/texture.frag.spv b/shaders/slang/dynamicrendering/texture.frag.spv deleted file mode 100644 index 72086329..00000000 Binary files a/shaders/slang/dynamicrendering/texture.frag.spv and /dev/null differ diff --git a/shaders/slang/dynamicrendering/texture.slang b/shaders/slang/dynamicrendering/texture.slang deleted file mode 100644 index baed6d6d..00000000 --- a/shaders/slang/dynamicrendering/texture.slang +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float3 Normal; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 viewPos; -}; -ConstantBuffer ubo; - -[[vk::binding(0, 1)]] Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - - float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lightPos = float3(0.0, 0.0, 0.0); - float3 lPos = mul((float3x3)ubo.model, lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerColor.Sample(input.UV); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a; - - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/dynamicrendering/texture.vert.spv b/shaders/slang/dynamicrendering/texture.vert.spv deleted file mode 100644 index e2f8ec88..00000000 Binary files a/shaders/slang/dynamicrendering/texture.vert.spv and /dev/null differ diff --git a/shaders/slang/dynamicuniformbuffer/base.frag.spv b/shaders/slang/dynamicuniformbuffer/base.frag.spv deleted file mode 100644 index 81761f27..00000000 Binary files a/shaders/slang/dynamicuniformbuffer/base.frag.spv and /dev/null differ diff --git a/shaders/slang/dynamicuniformbuffer/base.slang b/shaders/slang/dynamicuniformbuffer/base.slang deleted file mode 100644 index ec8e444d..00000000 --- a/shaders/slang/dynamicuniformbuffer/base.slang +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; -}; - -struct UboView -{ - float4x4 projection; - float4x4 view; -}; -ConstantBuffer uboView; - -struct UboInstance -{ - float4x4 model; -}; -ConstantBuffer uboInstance; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - float4x4 modelView = mul(uboView.view, uboInstance.model); - float3 worldPos = mul(modelView, float4(input.Pos, 1.0)).xyz; - output.Pos = mul(uboView.projection, mul(modelView, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/dynamicuniformbuffer/base.vert.spv b/shaders/slang/dynamicuniformbuffer/base.vert.spv deleted file mode 100644 index dceceb81..00000000 Binary files a/shaders/slang/dynamicuniformbuffer/base.vert.spv and /dev/null differ diff --git a/shaders/slang/gears/gears.frag.spv b/shaders/slang/gears/gears.frag.spv deleted file mode 100644 index e68f1691..00000000 Binary files a/shaders/slang/gears/gears.frag.spv and /dev/null differ diff --git a/shaders/slang/gears/gears.slang b/shaders/slang/gears/gears.slang deleted file mode 100644 index 5c15ba63..00000000 --- a/shaders/slang/gears/gears.slang +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 EyePos; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4 lightpos; - float4x4 model[3]; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uint InstanceIndex: SV_StartInstanceLocation) -{ - VSOutput output; - output.Normal = normalize(mul((float3x3)transpose(ubo.model[InstanceIndex]), input.Normal).xyz); - output.Color = input.Color; - float4x4 modelView = mul(ubo.view, ubo.model[InstanceIndex]); - float4 pos = mul(modelView, float4(input.Pos, 1.0)); - output.EyePos = mul(modelView, pos).xyz; - float4 lightPos = mul(float4(ubo.lightpos.xyz, 1.0), modelView); - output.LightVec = normalize(lightPos.xyz - output.EyePos); - output.Pos = mul(ubo.projection, pos); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 eye = normalize(-input.EyePos); - float3 reflected = normalize(reflect(-input.LightVec, input.Normal)); - - float4 ambient = float4(0.2, 0.2, 0.2, 1.0); - float4 diffuse = float4(0.5, 0.5, 0.5, 0.5) * max(dot(input.Normal, input.LightVec), 0.0); - float4 specular = float4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(reflected, eye), 0.0), 0.8) * 0.25; - - return float4((ambient + diffuse) * float4(input.Color, 1.0) + specular); -} \ No newline at end of file diff --git a/shaders/slang/gears/gears.vert.spv b/shaders/slang/gears/gears.vert.spv deleted file mode 100644 index 229baf7c..00000000 Binary files a/shaders/slang/gears/gears.vert.spv and /dev/null differ diff --git a/shaders/slang/geometryshader/base.frag.spv b/shaders/slang/geometryshader/base.frag.spv deleted file mode 100644 index 81761f27..00000000 Binary files a/shaders/slang/geometryshader/base.frag.spv and /dev/null differ diff --git a/shaders/slang/geometryshader/base.vert.spv b/shaders/slang/geometryshader/base.vert.spv deleted file mode 100644 index 9f78b1f8..00000000 Binary files a/shaders/slang/geometryshader/base.vert.spv and /dev/null differ diff --git a/shaders/slang/geometryshader/mesh.frag.spv b/shaders/slang/geometryshader/mesh.frag.spv deleted file mode 100644 index 6cbde14f..00000000 Binary files a/shaders/slang/geometryshader/mesh.frag.spv and /dev/null differ diff --git a/shaders/slang/geometryshader/mesh.slang b/shaders/slang/geometryshader/mesh.slang deleted file mode 100644 index fbe1e977..00000000 --- a/shaders/slang/geometryshader/mesh.slang +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, input.Pos)); - - float4 pos = mul(ubo.model, float4(input.Pos.xyz, 1.0)); - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - - float3 lightPos = float3(1.0f, -1.0f, 1.0f); - output.LightVec = lightPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.1, 0.1, 0.1); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/geometryshader/mesh.vert.spv b/shaders/slang/geometryshader/mesh.vert.spv deleted file mode 100644 index 6b136734..00000000 Binary files a/shaders/slang/geometryshader/mesh.vert.spv and /dev/null differ diff --git a/shaders/slang/geometryshader/normaldebug.geom.spv b/shaders/slang/geometryshader/normaldebug.geom.spv deleted file mode 100644 index dd1ba7a6..00000000 Binary files a/shaders/slang/geometryshader/normaldebug.geom.spv and /dev/null differ diff --git a/shaders/slang/geometryshader/normaldebug.slang b/shaders/slang/geometryshader/normaldebug.slang deleted file mode 100644 index 9b244d8d..00000000 --- a/shaders/slang/geometryshader/normaldebug.slang +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : POSITION0; - float3 Normal; -}; - -struct GSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Pos = float4(input.Pos.xyz, 1.0); - return output; -} - -[shader("geometry")] -[maxvertexcount(6)] -void geometryMain(triangle VSOutput input[3], inout LineStream outStream) -{ - float normalLength = 0.02; - for(int i=0; i<3; i++) - { - float3 pos = input[i].Pos.xyz; - float3 normal = input[i].Normal.xyz; - - GSOutput output = (GSOutput)0; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(pos, 1.0))); - output.Color = float3(1.0, 0.0, 0.0); - outStream.Append( output ); - - output.Pos = mul(ubo.projection, mul(ubo.model, float4(pos + normal * normalLength, 1.0))); - output.Color = float3(0.0, 0.0, 1.0); - outStream.Append( output ); - - outStream.RestartStrip(); - } -} - -[shader("fragment")] -float4 fragmentMain(GSOutput input) -{ - return float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/gltfloading/mesh.frag.spv b/shaders/slang/gltfloading/mesh.frag.spv deleted file mode 100644 index f19c72a0..00000000 Binary files a/shaders/slang/gltfloading/mesh.frag.spv and /dev/null differ diff --git a/shaders/slang/gltfloading/mesh.slang b/shaders/slang/gltfloading/mesh.slang deleted file mode 100644 index 7205d38f..00000000 --- a/shaders/slang/gltfloading/mesh.slang +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4 lightPos; - float4 viewPos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4x4 modelMat) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(modelMat, float4(input.Pos.xyz, 1.0)))); - - float4 pos = mul(ubo.view, mul(modelMat, float4(input.Pos.xyz, 1.0))); - output.Normal = mul((float3x3)ubo.view, input.Normal); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} - -[[vk::binding(0, 1)]] Sampler2D samplerColorMap; - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/gltfloading/mesh.vert.spv b/shaders/slang/gltfloading/mesh.vert.spv deleted file mode 100644 index 8af66eb7..00000000 Binary files a/shaders/slang/gltfloading/mesh.vert.spv and /dev/null differ diff --git a/shaders/slang/gltfscenerendering/scene.frag.spv b/shaders/slang/gltfscenerendering/scene.frag.spv deleted file mode 100644 index e36d3923..00000000 Binary files a/shaders/slang/gltfscenerendering/scene.frag.spv and /dev/null differ diff --git a/shaders/slang/gltfscenerendering/scene.slang b/shaders/slang/gltfscenerendering/scene.slang deleted file mode 100644 index b9ed1049..00000000 --- a/shaders/slang/gltfscenerendering/scene.slang +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; - float4 Tangent; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; - float3 ViewVec; - float3 LightVec; - float4 Tangent; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4 lightPos; - float4 viewPos; -}; -ConstantBuffer ubo; - -[[vk::binding(0, 1)]] Sampler2D samplerColorMap; -[[vk::binding(1, 1)]] Sampler2D samplerNormalMap; - -[SpecializationConstant] const bool ALPHA_MASK = false; -[SpecializationConstant] const float ALPHA_MASK_CUTOFF = 0.0; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4x4 modelMat) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Tangent = input.Tangent; - - float4x4 modelView = mul(ubo.view, modelMat); - - output.Pos = mul(ubo.projection, mul(modelView, float4(input.Pos.xyz, 1.0))); - - output.Normal = mul((float3x3)modelMat, input.Normal); - float4 pos = mul(modelMat, float4(input.Pos, 1.0)); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); - - if (ALPHA_MASK) { - if (color.a < ALPHA_MASK_CUTOFF) { - discard; - } - } - - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent.xyz); - float3 B = cross(input.Normal, input.Tangent.xyz) * input.Tangent.w; - float3x3 TBN = float3x3(T, B, N); - N = mul(normalize(samplerNormalMap.Sample(input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - - const float ambient = 0.1; - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), ambient).rrr; - float3 specular = pow(max(dot(R, V), 0.0), 32.0); - return float4(diffuse * color.rgb + specular, color.a); -} \ No newline at end of file diff --git a/shaders/slang/gltfscenerendering/scene.vert.spv b/shaders/slang/gltfscenerendering/scene.vert.spv deleted file mode 100644 index ecfc1b21..00000000 Binary files a/shaders/slang/gltfscenerendering/scene.vert.spv and /dev/null differ diff --git a/shaders/slang/gltfskinning/skinnedmodel.frag.spv b/shaders/slang/gltfskinning/skinnedmodel.frag.spv deleted file mode 100644 index 9dc302a9..00000000 Binary files a/shaders/slang/gltfskinning/skinnedmodel.frag.spv and /dev/null differ diff --git a/shaders/slang/gltfskinning/skinnedmodel.slang b/shaders/slang/gltfskinning/skinnedmodel.slang deleted file mode 100644 index 2d98836d..00000000 --- a/shaders/slang/gltfskinning/skinnedmodel.slang +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; - float4 JointIndices; - float4 JointWeights; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4 lightPos; - float4x4 inverse; -}; -ConstantBuffer uboScene; - -[[vk::binding(0, 1)]] StructuredBuffer jointMatrices; - -[[vk::binding(0, 2)]] Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4x4 modelMat) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - - // Calculate skinned matrix from weights and joint indices of the current vertex - float4x4 skinMat = - input.JointWeights.x * jointMatrices[int(input.JointIndices.x)] + - input.JointWeights.y * jointMatrices[int(input.JointIndices.y)] + - input.JointWeights.z * jointMatrices[int(input.JointIndices.z)] + - input.JointWeights.w * jointMatrices[int(input.JointIndices.w)]; - - output.Pos = mul(uboScene.projection, mul(uboScene.view, mul(modelMat, mul(skinMat, float4(input.Pos, 1.0))))); - output.Normal = mul((float3x3)modelMat, mul((float3x3)skinMat, input.Normal)); - - float4 pos = mul(uboScene.view, float4(input.Pos, 1.0)); - float3 lPos = mul(float3x3(uboScene.view), uboScene.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/gltfskinning/skinnedmodel.vert.spv b/shaders/slang/gltfskinning/skinnedmodel.vert.spv deleted file mode 100644 index 6c681788..00000000 Binary files a/shaders/slang/gltfskinning/skinnedmodel.vert.spv and /dev/null differ diff --git a/shaders/slang/graphicspipelinelibrary/shared.vert.spv b/shaders/slang/graphicspipelinelibrary/shared.vert.spv deleted file mode 100644 index c5f07810..00000000 Binary files a/shaders/slang/graphicspipelinelibrary/shared.vert.spv and /dev/null differ diff --git a/shaders/slang/graphicspipelinelibrary/uber.frag.spv b/shaders/slang/graphicspipelinelibrary/uber.frag.spv deleted file mode 100644 index b230418b..00000000 Binary files a/shaders/slang/graphicspipelinelibrary/uber.frag.spv and /dev/null differ diff --git a/shaders/slang/graphicspipelinelibrary/uber.slang b/shaders/slang/graphicspipelinelibrary/uber.slang deleted file mode 100644 index 0b582f54..00000000 --- a/shaders/slang/graphicspipelinelibrary/uber.slang +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -// We use this constant to control the flow of the shader depending on the -// lighting model selected at pipeline creation time -[[SpecializationConstant]] const int LIGHTING_MODEL = 0; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 outColor = float3(0.0); - - switch (LIGHTING_MODEL) { - case 0: // Phong - { - float3 ambient = input.Color * float3(0.25, 0.25, 0.25); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 32.0) * float3(0.75); - outColor = ambient + diffuse * 1.75 + specular; - break; - } - case 1: // Toon - { - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float intensity = dot(N, L); - float3 color; - if (intensity > 0.98) - color = input.Color * 1.5; - else if (intensity > 0.9) - color = input.Color * 1.0; - else if (intensity > 0.5) - color = input.Color * 0.6; - else if (intensity > 0.25) - color = input.Color * 0.4; - else - color = input.Color * 0.2; - outColor = color; - break; - } - case 2: // No shading - { - outColor = input.Color; - break; - } - case 3: // Greyscale - outColor = dot(input.Color, float3(0.299, 0.587, 0.114)); - break; - } - - // The scene itself is a bit dark, so brigthen it up a bit - return float4(outColor * 1.25, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/hdr/bloom.frag.spv b/shaders/slang/hdr/bloom.frag.spv deleted file mode 100644 index d94bf4b8..00000000 Binary files a/shaders/slang/hdr/bloom.frag.spv and /dev/null differ diff --git a/shaders/slang/hdr/bloom.slang b/shaders/slang/hdr/bloom.slang deleted file mode 100644 index 41a1ea6e..00000000 --- a/shaders/slang/hdr/bloom.slang +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -Sampler2D samplerColor0; -Sampler2D samplerColor1; - -[[SpecializationConstant]] const int dir = 0; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // From the OpenGL Super bible - const float weights[] = { 0.0024499299678342, - 0.0043538453346397, - 0.0073599963704157, - 0.0118349786570722, - 0.0181026699707781, - 0.0263392293891488, - 0.0364543006660986, - 0.0479932050577658, - 0.0601029809166942, - 0.0715974486241365, - 0.0811305381519717, - 0.0874493212267511, - 0.0896631113333857, - 0.0874493212267511, - 0.0811305381519717, - 0.0715974486241365, - 0.0601029809166942, - 0.0479932050577658, - 0.0364543006660986, - 0.0263392293891488, - 0.0181026699707781, - 0.0118349786570722, - 0.0073599963704157, - 0.0043538453346397, - 0.0024499299678342}; - - - const float blurScale = 0.003; - const float blurStrength = 1.0; - - float ar = 1.0; - // Aspect ratio for vertical blur pass - if (dir == 1) - { - float2 ts; - samplerColor1.GetDimensions(ts.x, ts.y); - ar = ts.y / ts.x; - } - - float2 P = input.UV.yx - float2(0, (25 >> 1) * ar * blurScale); - - float4 color = float4(0.0, 0.0, 0.0, 0.0); - for (int i = 0; i < 25; i++) - { - float2 dv = float2(0.0, i * blurScale) * ar; - color += samplerColor1.Sample(P + dv) * weights[i] * blurStrength; - } - - return color; -} \ No newline at end of file diff --git a/shaders/slang/hdr/bloom.vert.spv b/shaders/slang/hdr/bloom.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/hdr/bloom.vert.spv and /dev/null differ diff --git a/shaders/slang/hdr/composition.frag.spv b/shaders/slang/hdr/composition.frag.spv deleted file mode 100644 index a96badf3..00000000 Binary files a/shaders/slang/hdr/composition.frag.spv and /dev/null differ diff --git a/shaders/slang/hdr/composition.slang b/shaders/slang/hdr/composition.slang deleted file mode 100644 index d9705f60..00000000 --- a/shaders/slang/hdr/composition.slang +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColor.Sample(input.UV); -} \ No newline at end of file diff --git a/shaders/slang/hdr/composition.vert.spv b/shaders/slang/hdr/composition.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/hdr/composition.vert.spv and /dev/null differ diff --git a/shaders/slang/hdr/gbuffer.frag.spv b/shaders/slang/hdr/gbuffer.frag.spv deleted file mode 100644 index b42c3364..00000000 Binary files a/shaders/slang/hdr/gbuffer.frag.spv and /dev/null differ diff --git a/shaders/slang/hdr/gbuffer.slang b/shaders/slang/hdr/gbuffer.slang deleted file mode 100644 index ed0017a6..00000000 --- a/shaders/slang/hdr/gbuffer.slang +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; - float3 WorldPos; - float3 Normal; - float3 ViewVec; - float3 LightVec; -}; - -struct FSOutput -{ - float4 Color0 : SV_TARGET0; - float4 Color1 : SV_TARGET1; -}; - -struct UBO { - float4x4 projection; - float4x4 modelview; - float4x4 inverseModelview; - float exposure; -}; -ConstantBuffer ubo; - -SamplerCube samplerEnvMap; - -[[SpecializationConstant]] const int objectType = 0; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UVW = input.Pos; - - switch (objectType) { - case 0: // Skybox - output.WorldPos = mul((float4x3)ubo.modelview, input.Pos).xyz; - output.Pos = mul(ubo.projection, float4(output.WorldPos, 1.0)); - break; - case 1: // Object - output.WorldPos = mul(ubo.modelview, float4(input.Pos, 1.0)).xyz; - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(input.Pos.xyz, 1.0))); - break; - } - output.WorldPos = mul(ubo.modelview, float4(input.Pos, 1.0)).xyz; - output.Normal = mul((float4x3)ubo.modelview, input.Normal).xyz; - float3 lightPos = float3(0.0f, -5.0f, 5.0f); - output.LightVec = lightPos.xyz - output.WorldPos.xyz; - output.ViewVec = -output.WorldPos.xyz; - return output; -} - -[shader("fragment")] -FSOutput fragmentMain(VSOutput input) -{ - FSOutput output; - float4 color; - float3 wcNormal; - - switch (objectType) { - case 0: // Skybox - { - float3 normal = normalize(input.UVW); - color = samplerEnvMap.Sample(normal); - } - break; - - case 1: // Reflect - { - float3 wViewVec = mul((float4x3)ubo.inverseModelview, normalize(input.ViewVec)).xyz; - float3 normal = normalize(input.Normal); - float3 wNormal = mul((float4x3)ubo.inverseModelview, normal).xyz; - - float NdotL = max(dot(normal, input.LightVec), 0.0); - - float3 eyeDir = normalize(input.ViewVec); - float3 halfVec = normalize(input.LightVec + eyeDir); - float NdotH = max(dot(normal, halfVec), 0.0); - float NdotV = max(dot(normal, eyeDir), 0.0); - float VdotH = max(dot(eyeDir, halfVec), 0.0); - - // Geometric attenuation - float NH2 = 2.0 * NdotH; - float g1 = (NH2 * NdotV) / VdotH; - float g2 = (NH2 * NdotL) / VdotH; - float geoAtt = min(1.0, min(g1, g2)); - - const float F0 = 0.6; - const float k = 0.2; - - // Fresnel (schlick approximation) - float fresnel = pow(1.0 - VdotH, 5.0); - fresnel *= (1.0 - F0); - fresnel += F0; - - float spec = (fresnel * geoAtt) / (NdotV * NdotL * float.getPi()); - - color = samplerEnvMap.Sample(reflect(-wViewVec, wNormal)); - - color = float4(color.rgb * NdotL * (k + spec * (1.0 - k)), 1.0); - } - break; - - case 2: // Refract - { - float3 wViewVec = mul((float4x3)ubo.inverseModelview, normalize(input.ViewVec)).xyz; - float3 wNormal = mul((float4x3)ubo.inverseModelview, input.Normal).xyz; - color = samplerEnvMap.Sample(refract(-wViewVec, wNormal, 1.0/1.6)); - } - break; - } - - - // Color with manual exposure into attachment 0 - output.Color0.rgb = float3(1.0, 1.0, 1.0) - exp(-color.rgb * ubo.exposure); - - // Bright parts for bloom into attachment 1 - float l = dot(output.Color0.rgb, float3(0.2126, 0.7152, 0.0722)); - float threshold = 0.75; - output.Color1.rgb = (l > threshold) ? output.Color0.rgb : float3(0.0, 0.0, 0.0); - output.Color1.a = 1.0; - return output; -} \ No newline at end of file diff --git a/shaders/slang/hdr/gbuffer.vert.spv b/shaders/slang/hdr/gbuffer.vert.spv deleted file mode 100644 index 679f21c1..00000000 Binary files a/shaders/slang/hdr/gbuffer.vert.spv and /dev/null differ diff --git a/shaders/slang/imgui/scene.frag.spv b/shaders/slang/imgui/scene.frag.spv deleted file mode 100644 index 4704b77e..00000000 Binary files a/shaders/slang/imgui/scene.frag.spv and /dev/null differ diff --git a/shaders/slang/imgui/scene.slang b/shaders/slang/imgui/scene.slang deleted file mode 100644 index 5757b95c..00000000 --- a/shaders/slang/imgui/scene.slang +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - float3 lPos = mul((float4x3)ubo.model, ubo.lightPos.xyz).xyz; - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float diffuse = max(dot(N, L), 0.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse * input.Color + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/imgui/scene.vert.spv b/shaders/slang/imgui/scene.vert.spv deleted file mode 100644 index 59f4ae0d..00000000 Binary files a/shaders/slang/imgui/scene.vert.spv and /dev/null differ diff --git a/shaders/slang/imgui/ui.frag.spv b/shaders/slang/imgui/ui.frag.spv deleted file mode 100644 index f0054856..00000000 Binary files a/shaders/slang/imgui/ui.frag.spv and /dev/null differ diff --git a/shaders/slang/imgui/ui.slang b/shaders/slang/imgui/ui.slang deleted file mode 100644 index 603799e4..00000000 --- a/shaders/slang/imgui/ui.slang +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float2 Pos; - float2 UV; - float4 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float4 Color; -}; - -Sampler2D fontSampler; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float2 scale, uniform float2 translate) -{ - VSOutput output; - output.UV = input.UV; - output.Color = input.Color; - output.Pos = float4(input.Pos * scale + translate, 0.0, 1.0); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return input.Color * fontSampler.Sample(input.UV); -} \ No newline at end of file diff --git a/shaders/slang/imgui/ui.vert.spv b/shaders/slang/imgui/ui.vert.spv deleted file mode 100644 index d93356a3..00000000 Binary files a/shaders/slang/imgui/ui.vert.spv and /dev/null differ diff --git a/shaders/slang/indirectdraw/ground.frag.spv b/shaders/slang/indirectdraw/ground.frag.spv deleted file mode 100644 index e7f31fa7..00000000 Binary files a/shaders/slang/indirectdraw/ground.frag.spv and /dev/null differ diff --git a/shaders/slang/indirectdraw/ground.slang b/shaders/slang/indirectdraw/ground.slang deleted file mode 100644 index ac8624ac..00000000 --- a/shaders/slang/indirectdraw/ground.slang +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; -}; -ConstantBuffer ubo; - -[[vk::binding(2,0)]] Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV * 32.0; - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerColor.Sample(input.UV); - return float4(color.rgb, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/indirectdraw/ground.vert.spv b/shaders/slang/indirectdraw/ground.vert.spv deleted file mode 100644 index 5c18295e..00000000 Binary files a/shaders/slang/indirectdraw/ground.vert.spv and /dev/null differ diff --git a/shaders/slang/indirectdraw/indirectdraw.frag.spv b/shaders/slang/indirectdraw/indirectdraw.frag.spv deleted file mode 100644 index 48fdacc8..00000000 Binary files a/shaders/slang/indirectdraw/indirectdraw.frag.spv and /dev/null differ diff --git a/shaders/slang/indirectdraw/indirectdraw.slang b/shaders/slang/indirectdraw/indirectdraw.slang deleted file mode 100644 index 8c35d5e4..00000000 --- a/shaders/slang/indirectdraw/indirectdraw.slang +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Normal; - float2 UV; - float3 Color; - float3 instancePos; - float3 instanceRot; - float instanceScale; - int instanceTexIndex; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 UV; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; -}; -ConstantBuffer ubo; - -Sampler2DArray samplerArray; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.UV = float3(input.UV, input.instanceTexIndex); - - float4x4 mx, my, mz; - - // rotate around x - float s = sin(input.instanceRot.x); - float c = cos(input.instanceRot.x); - - mx[0] = float4(c, s, 0.0, 0.0); - mx[1] = float4(-s, c, 0.0, 0.0); - mx[2] = float4(0.0, 0.0, 1.0, 0.0); - mx[3] = float4(0.0, 0.0, 0.0, 1.0); - - // rotate around y - s = sin(input.instanceRot.y); - c = cos(input.instanceRot.y); - - my[0] = float4(c, 0.0, s, 0.0); - my[1] = float4(0.0, 1.0, 0.0, 0.0); - my[2] = float4(-s, 0.0, c, 0.0); - my[3] = float4(0.0, 0.0, 0.0, 1.0); - - // rot around z - s = sin(input.instanceRot.z); - c = cos(input.instanceRot.z); - - mz[0] = float4(1.0, 0.0, 0.0, 0.0); - mz[1] = float4(0.0, c, s, 0.0); - mz[2] = float4(0.0, -s, c, 0.0); - mz[3] = float4(0.0, 0.0, 0.0, 1.0); - - float4x4 rotMat = mul(mz, mul(my, mx)); - - output.Normal = mul((float4x3)rotMat, input.Normal).xyz; - - float4 pos = mul(rotMat, float4((input.Pos.xyz * input.instanceScale) + input.instancePos, 1.0)); - - output.Pos = mul(ubo.projection, mul(ubo.modelview, pos)); - - float4 wPos = mul(ubo.modelview, float4(pos.xyz, 1.0)); - float4 lPos = float4(0.0, -5.0, 0.0, 1.0); - output.LightVec = lPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerArray.Sample(input.UV); - - if (color.a < 0.5) - { - clip(-1); - } - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 ambient = float3(0.65, 0.65, 0.65); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - return float4((ambient + diffuse) * color.rgb, 1.0); -} diff --git a/shaders/slang/indirectdraw/indirectdraw.vert.spv b/shaders/slang/indirectdraw/indirectdraw.vert.spv deleted file mode 100644 index 728a257e..00000000 Binary files a/shaders/slang/indirectdraw/indirectdraw.vert.spv and /dev/null differ diff --git a/shaders/slang/indirectdraw/skysphere.frag.spv b/shaders/slang/indirectdraw/skysphere.frag.spv deleted file mode 100644 index 626d22b4..00000000 Binary files a/shaders/slang/indirectdraw/skysphere.frag.spv and /dev/null differ diff --git a/shaders/slang/indirectdraw/skysphere.slang b/shaders/slang/indirectdraw/skysphere.slang deleted file mode 100644 index 6bf4679e..00000000 --- a/shaders/slang/indirectdraw/skysphere.slang +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - // Skysphere always at center, only use rotation part of modelview matrix - output.Pos = mul(ubo.projection, float4(mul((float3x3)ubo.modelview, input.Pos.xyz), 1)); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - const float4 gradientStart = float4(0.93, 0.9, 0.81, 1.0); - const float4 gradientEnd = float4(0.35, 0.5, 1.0, 1.0); - return lerp(gradientStart, gradientEnd, min(0.5 - (input.UV.y + 0.05), 0.5)/0.15 - 0.5); -} \ No newline at end of file diff --git a/shaders/slang/indirectdraw/skysphere.vert.spv b/shaders/slang/indirectdraw/skysphere.vert.spv deleted file mode 100644 index 899b8f3b..00000000 Binary files a/shaders/slang/indirectdraw/skysphere.vert.spv and /dev/null differ diff --git a/shaders/slang/inlineuniformblocks/pbr.frag.spv b/shaders/slang/inlineuniformblocks/pbr.frag.spv deleted file mode 100644 index d5587b12..00000000 Binary files a/shaders/slang/inlineuniformblocks/pbr.frag.spv and /dev/null differ diff --git a/shaders/slang/inlineuniformblocks/pbr.slang b/shaders/slang/inlineuniformblocks/pbr.slang deleted file mode 100644 index 825d4902..00000000 --- a/shaders/slang/inlineuniformblocks/pbr.slang +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 WorldPos; - float3 Normal; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; -ConstantBuffer ubo; - -// Inline uniform block -struct UniformInline { - float roughness; - float metallic; - float r; - float g; - float b; - float ambient; -}; -[[vk::binding(0,1)]] ConstantBuffer material; - -#define PI 3.14159265359 -#define MATERIALCOLOR float3(material.r, material.g, material.b) - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -float3 F_Schlick(float cosTheta, float metallic) -{ - float3 F0 = lerp(float3(0.04, 0.04, 0.04), MATERIALCOLOR, metallic); // * material.specular - float3 F = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); - return F; -} - -// Specular BRDF composition -------------------------------------------- - -float3 BRDF(float3 L, float3 V, float3 N, float metallic, float roughness) -{ - // Precalculate vectors and dot products - float3 H = normalize (V + L); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - float dotLH = clamp(dot(L, H), 0.0, 1.0); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - - // Light color fixed - float3 lightColor = float3(1.0, 1.0, 1.0); - - float3 color = float3(0.0, 0.0, 0.0); - - if (dotNL > 0.0) - { - float rroughness = max(0.05, roughness); - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, rroughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, rroughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - float3 F = F_Schlick(dotNV, metallic); - - float3 spec = D * F * G / (4.0 * dotNL * dotNV); - - color += spec * dotNL * lightColor; - } - - return color; -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float3 objPos) -{ - VSOutput output; - float3 locPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.WorldPos = locPos + objPos; - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - output.Pos = mul(ubo.projection, mul(ubo.view, float4(output.WorldPos, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 V = normalize(ubo.camPos - input.WorldPos); - - float roughness = material.roughness; - - // Specular contribution - float3 lightPos = float3(0.0f, 0.0f, 10.0f); - float3 Lo = float3(0.0, 0.0, 0.0); - float3 L = normalize(lightPos.xyz - input.WorldPos); - Lo += BRDF(L, V, N, material.metallic, roughness); - - // Combine with ambient - float3 color = MATERIALCOLOR * material.ambient; - color += Lo; - - // Gamma correct - color = pow(color, float3(0.4545, 0.4545, 0.4545)); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/inlineuniformblocks/pbr.vert.spv b/shaders/slang/inlineuniformblocks/pbr.vert.spv deleted file mode 100644 index a5d0dc60..00000000 Binary files a/shaders/slang/inlineuniformblocks/pbr.vert.spv and /dev/null differ diff --git a/shaders/slang/inputattachments/attachmentread.frag.spv b/shaders/slang/inputattachments/attachmentread.frag.spv deleted file mode 100644 index 758bc4a3..00000000 Binary files a/shaders/slang/inputattachments/attachmentread.frag.spv and /dev/null differ diff --git a/shaders/slang/inputattachments/attachmentread.slang b/shaders/slang/inputattachments/attachmentread.slang deleted file mode 100644 index 3612f1ca..00000000 --- a/shaders/slang/inputattachments/attachmentread.slang +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; -}; - -[[vk::input_attachment_index(0)]] [[vk::binding(0)]] SubpassInput inputColor; -[[vk::input_attachment_index(1)]] [[vk::binding(1)]] SubpassInput inputDepth; - -struct UBO { - float2 brightnessContrast; - float2 range; - int attachmentIndex; -}; -ConstantBuffer ubo; - -float3 brightnessContrast(float3 color, float brightness, float contrast) { - return (color - 0.5) * contrast + 0.5 + brightness; -} - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.Pos = float4(float2((VertexIndex << 1) & 2, VertexIndex & 2) * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain() -{ - // Apply brightness and contrast filer to color input - if (ubo.attachmentIndex == 0) { - // Read color from previous color input attachment - float3 color = inputColor.SubpassLoad().rgb; - return float4(brightnessContrast(color, ubo.brightnessContrast[0], ubo.brightnessContrast[1]), 1.0); - } - - // Visualize depth input range - if (ubo.attachmentIndex == 1) { - // Read depth from previous depth input attachment - float depth = inputDepth.SubpassLoad().r; - return float4((depth - ubo.range[0]) * 1.0 / (ubo.range[1] - ubo.range[0]).xxx, 1.0); - } - - return float4(1.0); -} \ No newline at end of file diff --git a/shaders/slang/inputattachments/attachmentread.vert.spv b/shaders/slang/inputattachments/attachmentread.vert.spv deleted file mode 100644 index 36b0be4d..00000000 Binary files a/shaders/slang/inputattachments/attachmentread.vert.spv and /dev/null differ diff --git a/shaders/slang/inputattachments/attachmentwrite.frag.spv b/shaders/slang/inputattachments/attachmentwrite.frag.spv deleted file mode 100644 index 14f4a4f6..00000000 Binary files a/shaders/slang/inputattachments/attachmentwrite.frag.spv and /dev/null differ diff --git a/shaders/slang/inputattachments/attachmentwrite.slang b/shaders/slang/inputattachments/attachmentwrite.slang deleted file mode 100644 index e27e4e0e..00000000 --- a/shaders/slang/inputattachments/attachmentwrite.slang +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; - float3 Normal; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO { - float4x4 projection; - float4x4 model; - float4x4 view; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos, 1.0)))); - output.Color = input.Color; - output.Normal = input.Normal; - output.LightVec = float3(0.0f, 5.0f, 15.0f) - input.Pos; - output.ViewVec = -input.Pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Toon shading color attachment output - float intensity = dot(normalize(input.Normal), normalize(input.LightVec)); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - return float4(input.Color * 3.0 * shade, 1.0); - - // Depth attachment does not need to be explicitly written -} \ No newline at end of file diff --git a/shaders/slang/inputattachments/attachmentwrite.vert.spv b/shaders/slang/inputattachments/attachmentwrite.vert.spv deleted file mode 100644 index 804cdd5c..00000000 Binary files a/shaders/slang/inputattachments/attachmentwrite.vert.spv and /dev/null differ diff --git a/shaders/slang/instancing/instancing.frag.spv b/shaders/slang/instancing/instancing.frag.spv deleted file mode 100644 index cc5a2e2c..00000000 Binary files a/shaders/slang/instancing/instancing.frag.spv and /dev/null differ diff --git a/shaders/slang/instancing/instancing.slang b/shaders/slang/instancing/instancing.slang deleted file mode 100644 index 8541d187..00000000 --- a/shaders/slang/instancing/instancing.slang +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos : POSITION0; - float3 Normal : NORMAL0; - float2 UV : TEXCOORD0; - float3 Color : COLOR0; - // Instanced attributes - float3 instancePos : POSITION1; - float3 instanceRot : TEXCOORD1; - float instanceScale : TEXCOORD2; - int instanceTexIndex : TEXCOORD3; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 UV; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; - float locSpeed; - float globSpeed; -}; -ConstantBuffer ubo; -Sampler2DArray samplerArray; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.UV = float3(input.UV, input.instanceTexIndex); - - // rotate around x - float s = sin(input.instanceRot.x + ubo.locSpeed); - float c = cos(input.instanceRot.x + ubo.locSpeed); - - float3x3 mx = { c, -s, 0.0, - s, c, 0.0, - 0.0, 0.0, 1.0 }; - - // rotate around y - s = sin(input.instanceRot.y + ubo.locSpeed); - c = cos(input.instanceRot.y + ubo.locSpeed); - - float3x3 my = { c, 0.0, -s, - 0.0, 1.0, 0.0, - s, 0.0, c }; - - // rot around z - s = sin(input.instanceRot.z + ubo.locSpeed); - c = cos(input.instanceRot.z + ubo.locSpeed); - - float3x3 mz = { 1.0, 0.0, 0.0, - 0.0, c, -s, - 0.0, s, c }; - - float3x3 rotMat = mul(mz, mul(my, mx)); - - float4x4 gRotMat; - s = sin(input.instanceRot.y + ubo.globSpeed); - c = cos(input.instanceRot.y + ubo.globSpeed); - gRotMat[0] = float4(c, 0.0, -s, 0.0); - gRotMat[1] = float4(0.0, 1.0, 0.0, 0.0); - gRotMat[2] = float4(s, 0.0, c, 0.0); - gRotMat[3] = float4(0.0, 0.0, 0.0, 1.0); - - float4 locPos = float4(mul(rotMat, input.Pos.xyz), 1.0); - float4 pos = float4((locPos.xyz * input.instanceScale) + input.instancePos, 1.0); - - output.Pos = mul(ubo.projection, mul(ubo.modelview, mul(gRotMat, pos))); - output.Normal = mul((float3x3)mul(ubo.modelview, gRotMat), mul(rotMat, input.Normal)); - - pos = mul(ubo.modelview, float4(input.Pos.xyz + input.instancePos, 1.0)); - float3 lPos = mul((float3x3)ubo.modelview, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerArray.Sample(input.UV) * float4(input.Color, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.1) * input.Color; - float3 specular = (dot(N,L) > 0.0) ? pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75) * color.r : float3(0.0, 0.0, 0.0); - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/instancing/instancing.vert.spv b/shaders/slang/instancing/instancing.vert.spv deleted file mode 100644 index a4f2b676..00000000 Binary files a/shaders/slang/instancing/instancing.vert.spv and /dev/null differ diff --git a/shaders/slang/instancing/planet.frag.spv b/shaders/slang/instancing/planet.frag.spv deleted file mode 100644 index d0d62b0e..00000000 Binary files a/shaders/slang/instancing/planet.frag.spv and /dev/null differ diff --git a/shaders/slang/instancing/planet.slang b/shaders/slang/instancing/planet.slang deleted file mode 100644 index ca8bb346..00000000 --- a/shaders/slang/instancing/planet.slang +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; -}; -ConstantBuffer ubo; - -Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.modelview, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.modelview, input.Normal); - float3 lPos = mul((float3x3)ubo.modelview, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0) * 1.5; - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 4.0) * float3(0.5, 0.5, 0.5) * color.r; - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/instancing/planet.vert.spv b/shaders/slang/instancing/planet.vert.spv deleted file mode 100644 index cb3103ba..00000000 Binary files a/shaders/slang/instancing/planet.vert.spv and /dev/null differ diff --git a/shaders/slang/instancing/starfield.frag.spv b/shaders/slang/instancing/starfield.frag.spv deleted file mode 100644 index 846472b6..00000000 Binary files a/shaders/slang/instancing/starfield.frag.spv and /dev/null differ diff --git a/shaders/slang/instancing/starfield.slang b/shaders/slang/instancing/starfield.slang deleted file mode 100644 index 2a5fbab5..00000000 --- a/shaders/slang/instancing/starfield.slang +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#define HASHSCALE3 float3(443.897, 441.423, 437.195) -#define STARFREQUENCY 0.01 - -// Hash function by Dave Hoskins (https://www.shadertoy.com/view/4djSRW) -float hash33(float3 p3) -{ - p3 = frac(p3 * HASHSCALE3); - p3 += dot(p3, p3.yxz+float3(19.19, 19.19, 19.19)); - return frac((p3.x + p3.y)*p3.z + (p3.x+p3.z)*p3.y + (p3.y+p3.z)*p3.x); -} - -float3 starField(float3 pos) -{ - float3 color = float3(0.0, 0.0, 0.0); - float threshhold = (1.0 - STARFREQUENCY); - float rnd = hash33(pos); - if (rnd >= threshhold) - { - float starCol = pow((rnd - threshhold) / (1.0 - threshhold), 16.0); - color += starCol.xxx; - } - return color; -} - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; -}; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UVW = float3((VertexIndex << 1) & 2, VertexIndex & 2, VertexIndex & 2); - output.Pos = float4(output.UVW.xy * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(starField(input.UVW), 1.0); -} \ No newline at end of file diff --git a/shaders/slang/instancing/starfield.vert.spv b/shaders/slang/instancing/starfield.vert.spv deleted file mode 100644 index f60862cd..00000000 Binary files a/shaders/slang/instancing/starfield.vert.spv and /dev/null differ diff --git a/shaders/slang/meshshader/meshshader.frag.spv b/shaders/slang/meshshader/meshshader.frag.spv deleted file mode 100644 index 3d2c3eee..00000000 Binary files a/shaders/slang/meshshader/meshshader.frag.spv and /dev/null differ diff --git a/shaders/slang/meshshader/meshshader.mesh.spv b/shaders/slang/meshshader/meshshader.mesh.spv deleted file mode 100644 index 582ac173..00000000 Binary files a/shaders/slang/meshshader/meshshader.mesh.spv and /dev/null differ diff --git a/shaders/slang/meshshader/meshshader.slang b/shaders/slang/meshshader/meshshader.slang deleted file mode 100644 index 652b3411..00000000 --- a/shaders/slang/meshshader/meshshader.slang +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VertexOutput -{ - float4 position : SV_Position; - float4 color; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; -}; -ConstantBuffer ubo; - -static const float4 positions[3] = { - float4( 0.0, -1.0, 0.0, 1.0), - float4(-1.0, 1.0, 0.0, 1.0), - float4( 1.0, 1.0, 0.0, 1.0) -}; - -static const float4 colors[3] = { - float4(0.0, 1.0, 0.0, 1.0), - float4(0.0, 0.0, 1.0, 1.0), - float4(1.0, 0.0, 0.0, 1.0) -}; - -struct DummyPayLoad -{ - uint dummyData; -}; - -// We don't use pay loads in this sample, but the fn call requires one -groupshared DummyPayLoad dummyPayLoad; - -[shader("amplification")] -[numthreads(1, 1, 1)] -void amplificationMain() -{ - DispatchMesh(3, 1, 1, dummyPayLoad); -} - -[shader("mesh")] -[outputtopology("triangle")] -[numthreads(1, 1, 1)] -void meshMain(out indices uint3 triangles[1], out vertices VertexOutput vertices[3], uint3 DispatchThreadID : SV_DispatchThreadID) -{ - float4x4 mvp = mul(ubo.projection, mul(ubo.view, ubo.model)); - - float4 offset = float4(0.0, 0.0, float(DispatchThreadID.x), 0.0); - - SetMeshOutputCounts(3, 1); - for (uint i = 0; i < 3; i++) { - vertices[i].position = mul(mvp, positions[i] + offset); - vertices[i].color = colors[i]; - } - - SetMeshOutputCounts(3, 1); - triangles[0] = uint3(0, 1, 2); -} - -[shader("fragment")] -float4 fragmentMain(VertexOutput input) -{ - return input.color; -} diff --git a/shaders/slang/meshshader/meshshader.task.spv b/shaders/slang/meshshader/meshshader.task.spv deleted file mode 100644 index 735495e2..00000000 Binary files a/shaders/slang/meshshader/meshshader.task.spv and /dev/null differ diff --git a/shaders/slang/multisampling/mesh.frag.spv b/shaders/slang/multisampling/mesh.frag.spv deleted file mode 100644 index 3f797682..00000000 Binary files a/shaders/slang/multisampling/mesh.frag.spv and /dev/null differ diff --git a/shaders/slang/multisampling/mesh.slang b/shaders/slang/multisampling/mesh.slang deleted file mode 100644 index 840c1c24..00000000 --- a/shaders/slang/multisampling/mesh.slang +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -[[vk::binding(0,1)]] Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 0.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - input.Pos; - output.ViewVec = -input.Pos; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.15) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/multisampling/mesh.vert.spv b/shaders/slang/multisampling/mesh.vert.spv deleted file mode 100644 index b8c7e122..00000000 Binary files a/shaders/slang/multisampling/mesh.vert.spv and /dev/null differ diff --git a/shaders/slang/multithreading/phong.frag.spv b/shaders/slang/multithreading/phong.frag.spv deleted file mode 100644 index eefb9ff7..00000000 Binary files a/shaders/slang/multithreading/phong.frag.spv and /dev/null differ diff --git a/shaders/slang/multithreading/phong.slang b/shaders/slang/multithreading/phong.slang deleted file mode 100644 index ad82f3af..00000000 --- a/shaders/slang/multithreading/phong.slang +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4x4 mvp, uniform float3 color) -{ - VSOutput output; - if ((input.Color.r == 1.0) && (input.Color.g == 0.0) && (input.Color.b == 0.0)) - { - output.Color = color; - } - else - { - output.Color = input.Color; - } - output.Pos = mul(mvp, float4(input.Pos.xyz, 1.0)); - float4 pos = mul(mvp, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)mvp, input.Normal); - float3 lPos = float3(0.0, 0.0, 0.0); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/multithreading/phong.vert.spv b/shaders/slang/multithreading/phong.vert.spv deleted file mode 100644 index 45299783..00000000 Binary files a/shaders/slang/multithreading/phong.vert.spv and /dev/null differ diff --git a/shaders/slang/multithreading/starsphere.frag.spv b/shaders/slang/multithreading/starsphere.frag.spv deleted file mode 100644 index 332a5b65..00000000 Binary files a/shaders/slang/multithreading/starsphere.frag.spv and /dev/null differ diff --git a/shaders/slang/multithreading/starsphere.slang b/shaders/slang/multithreading/starsphere.slang deleted file mode 100644 index 2d6c492f..00000000 --- a/shaders/slang/multithreading/starsphere.slang +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#define HASHSCALE3 float3(443.897, 441.423, 437.195) -#define STARFREQUENCY 0.01 - -// Hash function by Dave Hoskins (https://www.shadertoy.com/view/4djSRW) -float hash33(float3 p3) -{ - p3 = frac(p3 * HASHSCALE3); - p3 += dot(p3, p3.yxz+float3(19.19, 19.19, 19.19)); - return frac((p3.x + p3.y)*p3.z + (p3.x+p3.z)*p3.y + (p3.y+p3.z)*p3.x); -} - -float3 starField(float3 pos) -{ - float3 color = float3(0.0, 0.0, 0.0); - float threshhold = (1.0 - STARFREQUENCY); - float rnd = hash33(pos); - if (rnd >= threshhold) - { - float starCol = pow((rnd - threshhold) / (1.0 - threshhold), 16.0); - color += starCol.xxx; - } - return color; -} - -struct VSInput -{ - float3 Pos; -} - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; -}; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4x4 mvp) -{ - VSOutput output; - output.UVW = input.Pos; - output.Pos = mul(mvp, float4(input.Pos.xyz, 1.0)); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Fake atmosphere at the bottom - float3 atmosphere = clamp(float3(0.1, 0.15, 0.4) * (input.UVW.y + 0.25), 0.0, 1.0); - float3 color = starField(input.UVW) + atmosphere; - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/multithreading/starsphere.vert.spv b/shaders/slang/multithreading/starsphere.vert.spv deleted file mode 100644 index 5d02106a..00000000 Binary files a/shaders/slang/multithreading/starsphere.vert.spv and /dev/null differ diff --git a/shaders/slang/multiview/multiview.frag.spv b/shaders/slang/multiview/multiview.frag.spv deleted file mode 100644 index 6cbde14f..00000000 Binary files a/shaders/slang/multiview/multiview.frag.spv and /dev/null differ diff --git a/shaders/slang/multiview/multiview.slang b/shaders/slang/multiview/multiview.slang deleted file mode 100644 index a4edbfa5..00000000 --- a/shaders/slang/multiview/multiview.slang +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection[2]; - float4x4 modelview[2]; - float4 lightPos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uint ViewIndex: SV_ViewID) -{ - VSOutput output; - output.Color = input.Color; - output.Normal = mul((float3x3)ubo.modelview[ViewIndex], input.Normal); - - float4 pos = float4(input.Pos.xyz, 1.0); - float4 worldPos = mul(ubo.modelview[ViewIndex], pos); - - float3 lPos = mul(ubo.modelview[ViewIndex], ubo.lightPos).xyz; - output.LightVec = lPos - worldPos.xyz; - output.ViewVec = -worldPos.xyz; - - output.Pos = mul(ubo.projection[ViewIndex], worldPos); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.1, 0.1, 0.1); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/multiview/multiview.vert.spv b/shaders/slang/multiview/multiview.vert.spv deleted file mode 100644 index 5fea5f90..00000000 Binary files a/shaders/slang/multiview/multiview.vert.spv and /dev/null differ diff --git a/shaders/slang/multiview/viewdisplay.frag.spv b/shaders/slang/multiview/viewdisplay.frag.spv deleted file mode 100644 index 59f7d45f..00000000 Binary files a/shaders/slang/multiview/viewdisplay.frag.spv and /dev/null differ diff --git a/shaders/slang/multiview/viewdisplay.slang b/shaders/slang/multiview/viewdisplay.slang deleted file mode 100644 index 4c982738..00000000 --- a/shaders/slang/multiview/viewdisplay.slang +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -struct UBO -{ - float4x4 projection[2]; - float4x4 modelview[2]; - float4 lightPos; - float distortionAlpha; -}; -ConstantBuffer ubo; - -Sampler2DArray samplerView; - -[[SpecializationConstant]] const float VIEW_LAYER = 0.0f; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - const float alpha = ubo.distortionAlpha; - - float2 p1 = float2(2.0 * input.UV - 1.0); - float2 p2 = p1 / (1.0 - alpha * length(p1)); - p2 = (p2 + 1.0) * 0.5; - - bool inside = ((p2.x >= 0.0) && (p2.x <= 1.0) && (p2.y >= 0.0) && (p2.y <= 1.0)); - return inside ? samplerView.Sample(float3(p2, VIEW_LAYER)) : float4(0.0, 0.0, 0.0, 0.0); -} \ No newline at end of file diff --git a/shaders/slang/multiview/viewdisplay.vert.spv b/shaders/slang/multiview/viewdisplay.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/multiview/viewdisplay.vert.spv and /dev/null differ diff --git a/shaders/slang/negativeviewportheight/quad.frag.spv b/shaders/slang/negativeviewportheight/quad.frag.spv deleted file mode 100644 index a96badf3..00000000 Binary files a/shaders/slang/negativeviewportheight/quad.frag.spv and /dev/null differ diff --git a/shaders/slang/negativeviewportheight/quad.slang b/shaders/slang/negativeviewportheight/quad.slang deleted file mode 100644 index 1ea13bb3..00000000 --- a/shaders/slang/negativeviewportheight/quad.slang +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ - float3 Pos; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - output.Pos = float4(input.Pos, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColor.Sample(input.UV); -} \ No newline at end of file diff --git a/shaders/slang/negativeviewportheight/quad.vert.spv b/shaders/slang/negativeviewportheight/quad.vert.spv deleted file mode 100644 index 74ba57ca..00000000 Binary files a/shaders/slang/negativeviewportheight/quad.vert.spv and /dev/null differ diff --git a/shaders/slang/occlusionquery/mesh.frag.spv b/shaders/slang/occlusionquery/mesh.frag.spv deleted file mode 100644 index e430e888..00000000 Binary files a/shaders/slang/occlusionquery/mesh.frag.spv and /dev/null differ diff --git a/shaders/slang/occlusionquery/mesh.slang b/shaders/slang/occlusionquery/mesh.slang deleted file mode 100644 index 50067670..00000000 --- a/shaders/slang/occlusionquery/mesh.slang +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float Visible; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 color; - float4 lightPos; - float visible; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color * ubo.color.rgb; - output.Visible = ubo.visible; - float4x4 modelView = mul(ubo.view, ubo.model); - output.Pos = mul(ubo.projection, mul(modelView, float4(input.Pos.xyz, 1.0))); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - if (input.Visible > 0.0) - { - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.25) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.75); - return float4(diffuse + specular, 1.0); - } - else - { - return float4(float3(0.1, 0.1, 0.1), 1.0); - } -} \ No newline at end of file diff --git a/shaders/slang/occlusionquery/mesh.vert.spv b/shaders/slang/occlusionquery/mesh.vert.spv deleted file mode 100644 index 7ace3836..00000000 Binary files a/shaders/slang/occlusionquery/mesh.vert.spv and /dev/null differ diff --git a/shaders/slang/occlusionquery/occluder.frag.spv b/shaders/slang/occlusionquery/occluder.frag.spv deleted file mode 100644 index 4fae9ce5..00000000 Binary files a/shaders/slang/occlusionquery/occluder.frag.spv and /dev/null differ diff --git a/shaders/slang/occlusionquery/occluder.slang b/shaders/slang/occlusionquery/occluder.slang deleted file mode 100644 index 7fa118d7..00000000 --- a/shaders/slang/occlusionquery/occluder.slang +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 color; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color * ubo.color.rgb; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(input.Color, 0.5); -} \ No newline at end of file diff --git a/shaders/slang/occlusionquery/occluder.vert.spv b/shaders/slang/occlusionquery/occluder.vert.spv deleted file mode 100644 index 6797ca69..00000000 Binary files a/shaders/slang/occlusionquery/occluder.vert.spv and /dev/null differ diff --git a/shaders/slang/occlusionquery/simple.frag.spv b/shaders/slang/occlusionquery/simple.frag.spv deleted file mode 100644 index 5cbccf9c..00000000 Binary files a/shaders/slang/occlusionquery/simple.frag.spv and /dev/null differ diff --git a/shaders/slang/occlusionquery/simple.slang b/shaders/slang/occlusionquery/simple.slang deleted file mode 100644 index 7cfc4bfd..00000000 --- a/shaders/slang/occlusionquery/simple.slang +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain() -{ - return float4(1.0, 1.0, 1.0, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/occlusionquery/simple.vert.spv b/shaders/slang/occlusionquery/simple.vert.spv deleted file mode 100644 index 2300613e..00000000 Binary files a/shaders/slang/occlusionquery/simple.vert.spv and /dev/null differ diff --git a/shaders/slang/offscreen/mirror.frag.spv b/shaders/slang/offscreen/mirror.frag.spv deleted file mode 100644 index 96a3cc8a..00000000 Binary files a/shaders/slang/offscreen/mirror.frag.spv and /dev/null differ diff --git a/shaders/slang/offscreen/mirror.slang b/shaders/slang/offscreen/mirror.slang deleted file mode 100644 index 49cf8791..00000000 --- a/shaders/slang/offscreen/mirror.slang +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float4 ProjCoord; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer ubo; - -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.ProjCoord = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - output.Pos = output.ProjCoord; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input, bool FrontFacing : SV_IsFrontFace) -{ - float4 tmp = (1.0 / input.ProjCoord.w).xxxx; - float4 projCoord = input.ProjCoord * tmp; - - // Scale and bias - projCoord += float4(1.0, 1.0, 1.0, 1.0); - projCoord *= float4(0.5, 0.5, 0.5, 0.5); - - // Slow single pass blur - // For demonstration purposes only - const float blurSize = 1.0 / 512.0; - - float4 color = float4(float3(0.0, 0.0, 0.0), 1.); - - if (FrontFacing) - { - // Only render mirrored scene on front facing (upper) side of mirror surface - float4 reflection = float4(0.0, 0.0, 0.0, 0.0); - for (int x = -3; x <= 3; x++) - { - for (int y = -3; y <= 3; y++) - { - reflection += samplerColor.Sample(float2(projCoord.x + x * blurSize, projCoord.y + y * blurSize)) / 49.0; - } - } - color += reflection; - } - - return color; -} \ No newline at end of file diff --git a/shaders/slang/offscreen/mirror.vert.spv b/shaders/slang/offscreen/mirror.vert.spv deleted file mode 100644 index 051ae484..00000000 Binary files a/shaders/slang/offscreen/mirror.vert.spv and /dev/null differ diff --git a/shaders/slang/offscreen/phong.frag.spv b/shaders/slang/offscreen/phong.frag.spv deleted file mode 100644 index ee0318fe..00000000 Binary files a/shaders/slang/offscreen/phong.frag.spv and /dev/null differ diff --git a/shaders/slang/offscreen/phong.slang b/shaders/slang/offscreen/phong.slang deleted file mode 100644 index e8743485..00000000 --- a/shaders/slang/offscreen/phong.slang +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float ClipDistance : SV_ClipDistance0; - float3 Normal; - float3 Color; - float3 EyePos; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos, 1.0)))); - output.EyePos = mul(ubo.view, mul(ubo.model, float4(input.Pos, 1.0))).xyz; - output.LightVec = normalize(ubo.lightPos.xyz - output.EyePos); - // Clip against reflection plane - float4 clipPlane = float4(0.0, 0.0, 0.0, 0.0); - output.ClipDistance = dot(float4(input.Pos, 1.0), clipPlane); - return output; -} - - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - float4 IAmbient = float4(0.1, 0.1, 0.1, 1.0); - float4 IDiffuse = max(dot(input.Normal, input.LightVec), 0.0).xxxx; - float specular = 0.75; - float4 ISpecular = float4(0.0, 0.0, 0.0, 0.0); - if (dot(input.EyePos, input.Normal) < 0.0) - { - ISpecular = float4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 16.0) * specular; - } - return float4((IAmbient + IDiffuse) * float4(input.Color, 1.0) + ISpecular); -} \ No newline at end of file diff --git a/shaders/slang/offscreen/phong.vert.spv b/shaders/slang/offscreen/phong.vert.spv deleted file mode 100644 index 5c92cb42..00000000 Binary files a/shaders/slang/offscreen/phong.vert.spv and /dev/null differ diff --git a/shaders/slang/offscreen/quad.frag.spv b/shaders/slang/offscreen/quad.frag.spv deleted file mode 100644 index a08f8ff1..00000000 Binary files a/shaders/slang/offscreen/quad.frag.spv and /dev/null differ diff --git a/shaders/slang/offscreen/quad.slang b/shaders/slang/offscreen/quad.slang deleted file mode 100644 index 49b0ebf7..00000000 --- a/shaders/slang/offscreen/quad.slang +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -[[vk::binding(1, 0)]] Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColor.Sample(input.UV); -} \ No newline at end of file diff --git a/shaders/slang/offscreen/quad.vert.spv b/shaders/slang/offscreen/quad.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/offscreen/quad.vert.spv and /dev/null differ diff --git a/shaders/slang/oit/color.frag.spv b/shaders/slang/oit/color.frag.spv deleted file mode 100644 index 9497a329..00000000 Binary files a/shaders/slang/oit/color.frag.spv and /dev/null differ diff --git a/shaders/slang/oit/color.slang b/shaders/slang/oit/color.slang deleted file mode 100644 index 7cda2767..00000000 --- a/shaders/slang/oit/color.slang +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#define MAX_FRAGMENT_COUNT 128 - -struct VSOutput -{ - float4 Pos : SV_POSITION; -}; - -struct Node -{ - float4 color; - float depth; - uint next; -}; -RWTexture2D headIndexImage; - -struct Particle -{ - float2 pos; - float2 vel; - float4 gradientPos; -}; -RWStructuredBuffer nodes; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - float2 UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - Node fragments[MAX_FRAGMENT_COUNT]; - int count = 0; - - uint nodeIdx = headIndexImage[uint2(input.Pos.xy)].r; - - while (nodeIdx != 0xffffffff && count < MAX_FRAGMENT_COUNT) - { - fragments[count] = nodes[nodeIdx]; - nodeIdx = fragments[count].next; - ++count; - } - - // Do the insertion sort - for (uint i = 1; i < count; ++i) - { - Node insert = fragments[i]; - uint j = i; - while (j > 0 && insert.depth > fragments[j - 1].depth) - { - fragments[j] = fragments[j-1]; - --j; - } - fragments[j] = insert; - } - - // Do blending - float4 color = float4(0.025, 0.025, 0.025, 1.0f); - for (uint f = 0; f < count; ++f) - { - color = lerp(color, fragments[f].color, fragments[f].color.a); - } - - return color; -} \ No newline at end of file diff --git a/shaders/slang/oit/color.vert.spv b/shaders/slang/oit/color.vert.spv deleted file mode 100644 index 1c5bdbdc..00000000 Binary files a/shaders/slang/oit/color.vert.spv and /dev/null differ diff --git a/shaders/slang/oit/geometry.frag.spv b/shaders/slang/oit/geometry.frag.spv deleted file mode 100644 index 4a6c62d3..00000000 Binary files a/shaders/slang/oit/geometry.frag.spv and /dev/null differ diff --git a/shaders/slang/oit/geometry.slang b/shaders/slang/oit/geometry.slang deleted file mode 100644 index 1a72580d..00000000 --- a/shaders/slang/oit/geometry.slang +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos : POSITION0; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -}; - -struct RenderPassUBO -{ - float4x4 projection; - float4x4 view; -}; -ConstantBuffer renderPassUBO; - -struct GeometrySBO -{ - uint count; - uint maxNodeCount; -}; -// Binding 0 : Position storage buffer -RWStructuredBuffer geometrySBO; - -struct Node -{ - float4 color; - float depth; - uint next; -}; -RWTexture2D headIndexImage; - -RWStructuredBuffer nodes; - -struct PushConsts { - float4x4 model; - float4 color; -}; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform PushConsts pushConsts) -{ - VSOutput output; - output.Pos = mul(renderPassUBO.projection, mul(renderPassUBO.view, mul(pushConsts.model, input.Pos))); - return output; -} - -[shader("fragment")] -[earlydepthstencil] -void fragmentMain(VSOutput input, uniform PushConsts pushConsts) -{ - // Increase the node count - uint nodeIdx; - InterlockedAdd(geometrySBO[0].count, 1, nodeIdx); - - // Check LinkedListSBO is full - if (nodeIdx < geometrySBO[0].maxNodeCount) - { - // Exchange new head index and previous head index - uint prevHeadIdx; - InterlockedExchange(headIndexImage[uint2(input.Pos.xy)], nodeIdx, prevHeadIdx); - - // Store node data - nodes[nodeIdx].color = pushConsts.color; - nodes[nodeIdx].depth = input.Pos.z; - nodes[nodeIdx].next = prevHeadIdx; - } -} \ No newline at end of file diff --git a/shaders/slang/oit/geometry.vert.spv b/shaders/slang/oit/geometry.vert.spv deleted file mode 100644 index 7a558843..00000000 Binary files a/shaders/slang/oit/geometry.vert.spv and /dev/null differ diff --git a/shaders/slang/parallaxmapping/parallax.frag.spv b/shaders/slang/parallaxmapping/parallax.frag.spv deleted file mode 100644 index 45b3cf03..00000000 Binary files a/shaders/slang/parallaxmapping/parallax.frag.spv and /dev/null differ diff --git a/shaders/slang/parallaxmapping/parallax.slang b/shaders/slang/parallaxmapping/parallax.slang deleted file mode 100644 index aa0c1048..00000000 --- a/shaders/slang/parallaxmapping/parallax.slang +++ /dev/null @@ -1,150 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct UBOScene -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; - float4 cameraPos; -}; -ConstantBuffer uboScene; - -Sampler2D samplerColorMap; -Sampler2D samplerNormalHeightMap; - -struct UBOParams -{ - float heightScale; - float parallaxBias; - float numLayers; - int mappingMode; -}; -ConstantBuffer uboParams; - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Normal; - float4 Tangent; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float3 TangentLightPos; - float3 TangentViewPos; - float3 TangentFragPos; -}; - -float2 parallaxMapping(float2 uv, float3 viewDir) -{ - float height = 1.0 - samplerNormalHeightMap.SampleLevel(uv, 0.0).a; - float2 p = viewDir.xy * (height * (uboParams.heightScale * 0.5) + uboParams.parallaxBias) / viewDir.z; - return uv - p; -} - -float2 steepParallaxMapping(float2 uv, float3 viewDir) -{ - float layerDepth = 1.0 / uboParams.numLayers; - float currLayerDepth = 0.0; - float2 deltaUV = viewDir.xy * uboParams.heightScale / (viewDir.z * uboParams.numLayers); - float2 currUV = uv; - float height = 1.0 - samplerNormalHeightMap.SampleLevel(currUV, 0.0).a; - for (int i = 0; i < uboParams.numLayers; i++) { - currLayerDepth += layerDepth; - currUV -= deltaUV; - height = 1.0 - samplerNormalHeightMap.SampleLevel(currUV, 0.0).a; - if (height < currLayerDepth) { - break; - } - } - return currUV; -} - -float2 parallaxOcclusionMapping(float2 uv, float3 viewDir) -{ - float layerDepth = 1.0 / uboParams.numLayers; - float currLayerDepth = 0.0; - float2 deltaUV = viewDir.xy * uboParams.heightScale / (viewDir.z * uboParams.numLayers); - float2 currUV = uv; - float height = 1.0 - samplerNormalHeightMap.SampleLevel(currUV, 0.0).a; - for (int i = 0; i < uboParams.numLayers; i++) { - currLayerDepth += layerDepth; - currUV -= deltaUV; - height = 1.0 - samplerNormalHeightMap.SampleLevel(currUV, 0.0).a; - if (height < currLayerDepth) { - break; - } - } - float2 prevUV = currUV + deltaUV; - float nextDepth = height - currLayerDepth; - float prevDepth = 1.0 - samplerNormalHeightMap.SampleLevel(prevUV, 0.0).a - currLayerDepth + layerDepth; - return lerp(currUV, prevUV, nextDepth / (nextDepth - prevDepth)); -} - -[shader("vertex")] - -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = mul(uboScene.projection, mul(uboScene.view, mul(uboScene.model, float4(input.Pos, 1.0f)))); - output.UV = input.UV; - - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent.xyz); - float3 B = normalize(cross(N, T)); - float3x3 TBN = float3x3(T, B, N); - - output.TangentLightPos = mul(TBN, uboScene.lightPos.xyz); - output.TangentViewPos = mul(TBN, uboScene.cameraPos.xyz); - output.TangentFragPos = mul(TBN, mul(uboScene.model, float4(input.Pos, 1.0)).xyz); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 V = normalize(input.TangentViewPos - input.TangentFragPos); - float2 uv = input.UV; - - if (uboParams.mappingMode == 0) { - // Color only - return samplerColorMap.Sample(input.UV); - } else { - switch (uboParams.mappingMode) { - case 2: - uv = parallaxMapping(input.UV, V); - break; - case 3: - uv = steepParallaxMapping(input.UV, V); - break; - case 4: - uv = parallaxOcclusionMapping(input.UV, V); - break; - } - - // Discard fragments at texture border - if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) { - clip(-1); - } - - float3 N = normalize(samplerNormalHeightMap.SampleLevel(uv, 0.0).rgb * 2.0 - 1.0); - float3 L = normalize(input.TangentLightPos - input.TangentFragPos); - float3 R = reflect(-L, N); - float3 H = normalize(L + V); - - float3 color = samplerColorMap.Sample(uv).rgb; - float3 ambient = 0.2 * color; - float3 diffuse = max(dot(L, N), 0.0) * color; - float3 specular = float3(0.15, 0.15, 0.15) * pow(max(dot(N, H), 0.0), 32.0); - - return float4(ambient + diffuse + specular, 1.0f); - } -} diff --git a/shaders/slang/parallaxmapping/parallax.vert.spv b/shaders/slang/parallaxmapping/parallax.vert.spv deleted file mode 100644 index 3999403a..00000000 Binary files a/shaders/slang/parallaxmapping/parallax.vert.spv and /dev/null differ diff --git a/shaders/slang/particlesystem/normalmap.frag.spv b/shaders/slang/particlesystem/normalmap.frag.spv deleted file mode 100644 index 9be89681..00000000 Binary files a/shaders/slang/particlesystem/normalmap.frag.spv and /dev/null differ diff --git a/shaders/slang/particlesystem/normalmap.slang b/shaders/slang/particlesystem/normalmap.slang deleted file mode 100644 index 6b471e4b..00000000 --- a/shaders/slang/particlesystem/normalmap.slang +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Normal; - float4 Tangent; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float3 LightVec; - float3 LightVecB; - float3 LightDir; - float3 ViewVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 normal; - float4 lightPos; -}; -ConstantBuffer ubo; - -Sampler2D samplerColorMap; -Sampler2D samplerNormalHeightMap; - -#define lightRadius 45.0 - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - float3 vertexPosition = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.LightDir = normalize(ubo.lightPos.xyz - vertexPosition); - - float3 biTangent = cross(input.Normal, input.Tangent.xyz); - - // Setup (t)angent-(b)inormal-(n)ormal matrix for converting - // object coordinates into tangent space - float3x3 tbnMatrix; - tbnMatrix[0] = mul((float3x3)ubo.normal, input.Tangent.xyz); - tbnMatrix[1] = mul((float3x3)ubo.normal, biTangent); - tbnMatrix[2] = mul((float3x3)ubo.normal, input.Normal); - - output.LightVec.xyz = mul(float3(ubo.lightPos.xyz - vertexPosition), tbnMatrix); - - float3 lightDist = ubo.lightPos.xyz - input.Pos; - output.LightVecB.x = dot(input.Tangent.xyz, lightDist); - output.LightVecB.y = dot(biTangent, lightDist); - output.LightVecB.z = dot(input.Normal, lightDist); - - output.ViewVec.x = dot(input.Tangent.xyz, input.Pos); - output.ViewVec.y = dot(biTangent, input.Pos); - output.ViewVec.z = dot(input.Normal, input.Pos); - - output.UV = input.UV; - - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 specularColor = float3(0.85, 0.5, 0.0); - - float invRadius = 1.0/lightRadius; - float ambient = 0.25; - - float3 rgb, normal; - - rgb = samplerColorMap.Sample(input.UV).rgb; - normal = normalize((samplerNormalHeightMap.Sample(input.UV).rgb - 0.5) * 2.0); - - float distSqr = dot(input.LightVecB, input.LightVecB); - float3 lVec = input.LightVecB * rsqrt(distSqr); - - float atten = max(clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0), ambient); - float diffuse = clamp(dot(lVec, normal), 0.0, 1.0); - - float3 light = normalize(-input.LightVec); - float3 view = normalize(input.ViewVec); - float3 reflectDir = reflect(-light, normal); - - float specular = pow(max(dot(view, reflectDir), 0.0), 4.0); - - return float4((rgb * atten + (diffuse * rgb + 0.5 * specular * specularColor.rgb)) * atten, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/particlesystem/normalmap.vert.spv b/shaders/slang/particlesystem/normalmap.vert.spv deleted file mode 100644 index 9bc1b06a..00000000 Binary files a/shaders/slang/particlesystem/normalmap.vert.spv and /dev/null differ diff --git a/shaders/slang/particlesystem/particle.frag.spv b/shaders/slang/particlesystem/particle.frag.spv deleted file mode 100644 index e0988cb6..00000000 Binary files a/shaders/slang/particlesystem/particle.frag.spv and /dev/null differ diff --git a/shaders/slang/particlesystem/particle.slang b/shaders/slang/particlesystem/particle.slang deleted file mode 100644 index d479260c..00000000 --- a/shaders/slang/particlesystem/particle.slang +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float4 Color; - float Alpha; - float Size; - float Rotation; - int Type; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float PSize : SV_PointSize; - float4 Color; - float Alpha; - int Type; - float Rotation; - float2 CenterPos; - float PointSize; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float2 viewportDim; - float pointSize; -}; -ConstantBuffer ubo; - -Sampler2D samplerSmoke; -Sampler2D samplerFire; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Alpha = input.Alpha; - output.Type = input.Type; - output.Rotation = input.Rotation; - - output.Pos = mul(ubo.projection, mul(ubo.modelview, float4(input.Pos.xyz, 1.0))); - - // Base size of the point sprites - float spriteSize = 8.0 * input.Size; - - // Scale particle size depending on camera projection - float4 eyePos = mul(ubo.modelview, float4(input.Pos.xyz, 1.0)); - float4 projectedCorner = mul(ubo.projection, float4(0.5 * spriteSize, 0.5 * spriteSize, eyePos.z, eyePos.w)); - output.PointSize = output.PSize = ubo.viewportDim.x * projectedCorner.x / projectedCorner.w; - output.CenterPos = ((output.Pos.xy / output.Pos.w) + 1.0) * 0.5 * ubo.viewportDim; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color; - float alpha = (input.Alpha <= 1.0) ? input.Alpha : 2.0 - input.Alpha; - - // Rotate texture coordinates - // Rotate UV - float rotCenter = 0.5; - float rotCos = cos(input.Rotation); - float rotSin = sin(input.Rotation); - - float2 PointCoord = (input.Pos.xy - input.CenterPos.xy) / input.PointSize + 0.5; - - float2 rotUV = float2( - rotCos * (PointCoord.x - rotCenter) + rotSin * (PointCoord.y - rotCenter) + rotCenter, - rotCos * (PointCoord.y - rotCenter) - rotSin * (PointCoord.x - rotCenter) + rotCenter); - - float4 outFragColor; - if (input.Type == 0) - { - // Flame - color = samplerFire.Sample(rotUV); - outFragColor.a = 0.0; - } - else - { - // Smoke - color = samplerSmoke.Sample(rotUV); - outFragColor.a = color.a * alpha; - } - - outFragColor.rgb = color.rgb * input.Color.rgb * alpha; - return outFragColor; -} \ No newline at end of file diff --git a/shaders/slang/particlesystem/particle.vert.spv b/shaders/slang/particlesystem/particle.vert.spv deleted file mode 100644 index f0911192..00000000 Binary files a/shaders/slang/particlesystem/particle.vert.spv and /dev/null differ diff --git a/shaders/slang/pbrbasic/pbr.frag.spv b/shaders/slang/pbrbasic/pbr.frag.spv deleted file mode 100644 index 8e06c66a..00000000 Binary files a/shaders/slang/pbrbasic/pbr.frag.spv and /dev/null differ diff --git a/shaders/slang/pbrbasic/pbr.slang b/shaders/slang/pbrbasic/pbr.slang deleted file mode 100644 index 242d0fc9..00000000 --- a/shaders/slang/pbrbasic/pbr.slang +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 WorldPos; - float3 Normal; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; -ConstantBuffer ubo; - -struct UBOParams { - float4 lights[4]; -}; -ConstantBuffer uboParams; - -struct Material { - [[vk::offset(12)]] float roughness; - [[vk::offset(16)]] float metallic; - [[vk::offset(20)]] float r; - [[vk::offset(24)]] float g; - [[vk::offset(28)]] float b; -}; -[[vk::push_constant]] Material material; - -static const float PI = 3.14159265359; - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -float3 F_Schlick(float cosTheta, Material material) -{ - float3 F0 = lerp(float3(0.04, 0.04, 0.04), float3(material.r, material.g, material.b), material.metallic); // * material.specular - float3 F = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); - return F; -} - -// Specular BRDF composition -------------------------------------------- - -float3 BRDF(float3 L, float3 V, float3 N, Material material) -{ - // Precalculate vectors and dot products - float3 H = normalize (V + L); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - float dotLH = clamp(dot(L, H), 0.0, 1.0); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - - // Light color fixed - float3 lightColor = float3(1.0, 1.0, 1.0); - - float3 color = float3(0.0, 0.0, 0.0); - - if (dotNL > 0.0) - { - float rroughness = max(0.05, material.roughness); - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, material.roughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, rroughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - float3 F = F_Schlick(dotNV, material); - - float3 spec = D * F * G / (4.0 * dotNL * dotNV); - - color += spec * dotNL * lightColor; - } - - return color; -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float3 objPos) -{ - VSOutput output; - float3 locPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.WorldPos = locPos + objPos; - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.Pos = mul(ubo.projection, mul(ubo.view, float4(output.WorldPos, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 V = normalize(ubo.camPos - input.WorldPos); - - // Specular contribution - float3 Lo = float3(0.0, 0.0, 0.0); - for (int i = 0; i < 4; i++) { - float3 L = normalize(uboParams.lights[i].xyz - input.WorldPos); - Lo += BRDF(L, V, N, material); - }; - - // Combine with ambient - float3 color = float3(material.r, material.g, material.b) * 0.02; - color += Lo; - - // Gamma correct - color = pow(color, float3(0.4545, 0.4545, 0.4545)); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/pbrbasic/pbr.vert.spv b/shaders/slang/pbrbasic/pbr.vert.spv deleted file mode 100644 index 763c4205..00000000 Binary files a/shaders/slang/pbrbasic/pbr.vert.spv and /dev/null differ diff --git a/shaders/slang/pbribl/filtercube.slang b/shaders/slang/pbribl/filtercube.slang deleted file mode 100644 index 6c848459..00000000 --- a/shaders/slang/pbribl/filtercube.slang +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; -}; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4x4 mvp) -{ - VSOutput output; - output.UVW = input.Pos; - output.Pos = mul(mvp, float4(input.Pos.xyz, 1.0)); - return output; -} diff --git a/shaders/slang/pbribl/filtercube.vert.spv b/shaders/slang/pbribl/filtercube.vert.spv deleted file mode 100644 index 5d02106a..00000000 Binary files a/shaders/slang/pbribl/filtercube.vert.spv and /dev/null differ diff --git a/shaders/slang/pbribl/genbrdflut.frag.spv b/shaders/slang/pbribl/genbrdflut.frag.spv deleted file mode 100644 index a055c41e..00000000 Binary files a/shaders/slang/pbribl/genbrdflut.frag.spv and /dev/null differ diff --git a/shaders/slang/pbribl/genbrdflut.slang b/shaders/slang/pbribl/genbrdflut.slang deleted file mode 100644 index b40d7b16..00000000 --- a/shaders/slang/pbribl/genbrdflut.slang +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - - struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -[[SpecializationConstant]] const uint NUM_SAMPLES = 1024u; - -#define PI 3.1415926536 - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(float2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,float2(a,b)); - float sn= fmod(dt,3.14); - return frac(sin(sn) * c); -} - -float2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return float2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -float3 importanceSample_GGX(float2 Xi, float roughness, float3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - float3 up = abs(normal.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); - float3 tangentX = normalize(cross(up, normal)); - float3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Geometric Shadowing function -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float k = (roughness * roughness) / 2.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -float2 BRDF(float NoV, float roughness) -{ - // Normal always points along z-axis for the 2D lookup - const float3 N = float3(0.0, 0.0, 1.0); - float3 V = float3(sqrt(1.0 - NoV*NoV), 0.0, NoV); - - float2 LUT = float2(0.0, 0.0); - for(uint i = 0u; i < NUM_SAMPLES; i++) { - float2 Xi = hammersley2d(i, NUM_SAMPLES); - float3 H = importanceSample_GGX(Xi, roughness, N); - float3 L = 2.0 * dot(V, H) * H - V; - - float dotNL = max(dot(N, L), 0.0); - float dotNV = max(dot(N, V), 0.0); - float dotVH = max(dot(V, H), 0.0); - float dotNH = max(dot(H, N), 0.0); - - if (dotNL > 0.0) { - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - float G_Vis = (G * dotVH) / (dotNH * dotNV); - float Fc = pow(1.0 - dotVH, 5.0); - LUT += float2((1.0 - Fc) * G_Vis, Fc * G_Vis); - } - } - return LUT / float(NUM_SAMPLES); -} - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(BRDF(input.UV.x, input.UV.y), 0.0, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/pbribl/genbrdflut.vert.spv b/shaders/slang/pbribl/genbrdflut.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/pbribl/genbrdflut.vert.spv and /dev/null differ diff --git a/shaders/slang/pbribl/irradiancecube.frag.spv b/shaders/slang/pbribl/irradiancecube.frag.spv deleted file mode 100644 index 8941b9b3..00000000 Binary files a/shaders/slang/pbribl/irradiancecube.frag.spv and /dev/null differ diff --git a/shaders/slang/pbribl/irradiancecube.slang b/shaders/slang/pbribl/irradiancecube.slang deleted file mode 100644 index 31cc96ea..00000000 --- a/shaders/slang/pbribl/irradiancecube.slang +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -SamplerCube samplerEnv; - -struct PushConsts { - [[vk::offset(64)]] float deltaPhi; - [[vk::offset(68)]] float deltaTheta; -}; -[[vk::push_constant]] PushConsts consts; - -#define PI 3.1415926535897932384626433832795 - -[shader("fragment")] -float4 fragmentMain(float3 inPos) -{ - float3 N = normalize(inPos.xyz); - float3 up = float3(0.0, 1.0, 0.0); - float3 right = normalize(cross(up, N)); - up = cross(N, right); - - const float TWO_PI = PI * 2.0; - const float HALF_PI = PI * 0.5; - - float3 color = float3(0.0, 0.0, 0.0); - uint sampleCount = 0u; - for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) { - for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) { - float3 tempVec = cos(phi) * right + sin(phi) * up; - float3 sampleVector = cos(theta) * N + sin(theta) * tempVec; - color += samplerEnv.Sample(sampleVector).rgb * cos(theta) * sin(theta); - sampleCount++; - } - } - return float4(PI * color / float(sampleCount), 1.0); -} diff --git a/shaders/slang/pbribl/pbribl.frag.spv b/shaders/slang/pbribl/pbribl.frag.spv deleted file mode 100644 index 44c5bf75..00000000 Binary files a/shaders/slang/pbribl/pbribl.frag.spv and /dev/null differ diff --git a/shaders/slang/pbribl/pbribl.slang b/shaders/slang/pbribl/pbribl.slang deleted file mode 100644 index 6ced37ff..00000000 --- a/shaders/slang/pbribl/pbribl.slang +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 WorldPos; - float3 Normal; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; -ConstantBuffer ubo; - -struct UBOParams { - float4 lights[4]; - float exposure; - float gamma; -}; -ConstantBuffer uboParams; - -SamplerCube samplerIrradiance; -Sampler2D samplerBRDFLUT; -SamplerCube prefilteredMapSampler; - -struct Material { - [[vk::offset(12)]] float roughness; - [[vk::offset(16)]] float metallic; - [[vk::offset(20)]] float specular; - [[vk::offset(24)]] float r; - [[vk::offset(28)]] float g; - [[vk::offset(32)]] float b; -}; -[[vk::push_constant]] Material material; - -#define PI 3.1415926535897932384626433832795 -#define ALBEDO float3(material.r, material.g, material.b) - -// From http://filmicgames.com/archives/75 -float3 Uncharted2Tonemap(float3 x) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F; -} - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -float3 F_Schlick(float cosTheta, float3 F0) -{ - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} -float3 F_SchlickR(float cosTheta, float3 F0, float roughness) -{ - return F0 + (max((1.0 - roughness).xxx, F0) - F0) * pow(1.0 - cosTheta, 5.0); -} - -float3 prefilteredReflection(float3 R, float roughness) -{ - const float MAX_REFLECTION_LOD = 9.0; // todo: param/const - float lod = roughness * MAX_REFLECTION_LOD; - float lodf = floor(lod); - float lodc = ceil(lod); - float3 a = prefilteredMapSampler.SampleLevel(R, lodf).rgb; - float3 b = prefilteredMapSampler.SampleLevel(R, lodc).rgb; - return lerp(a, b, lod - lodf); -} - -float3 specularContribution(float3 L, float3 V, float3 N, float3 F0, float metallic, float roughness) -{ - // Precalculate vectors and dot products - float3 H = normalize (V + L); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - - // Light color fixed - float3 lightColor = float3(1.0, 1.0, 1.0); - - float3 color = float3(0.0, 0.0, 0.0); - - if (dotNL > 0.0) { - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, roughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - float3 F = F_Schlick(dotNV, F0); - float3 spec = D * F * G / (4.0 * dotNL * dotNV + 0.001); - float3 kD = (float3(1.0, 1.0, 1.0) - F) * (1.0 - metallic); - color += (kD * ALBEDO / PI + spec) * dotNL; - } - - return color; -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float3 objPos) -{ - VSOutput output; - float3 locPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.WorldPos = locPos + objPos; - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.UV = input.UV; - output.UV.y = 1.0 - input.UV.y; - output.Pos = mul(ubo.projection, mul(ubo.view, float4(output.WorldPos, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 V = normalize(ubo.camPos - input.WorldPos); - float3 R = reflect(-V, N); - - float metallic = material.metallic; - float roughness = material.roughness; - - float3 F0 = float3(0.04, 0.04, 0.04); - F0 = lerp(F0, ALBEDO, metallic); - - float3 Lo = float3(0.0, 0.0, 0.0); - for(int i = 0; i < 4; i++) { - float3 L = normalize(uboParams.lights[i].xyz - input.WorldPos); - Lo += specularContribution(L, V, N, F0, metallic, roughness); - } - - float2 brdf = samplerBRDFLUT.Sample(float2(max(dot(N, V), 0.0), roughness)).rg; - float3 reflection = prefilteredReflection(R, roughness).rgb; - float3 irradiance = samplerIrradiance.Sample(N).rgb; - - // Diffuse based on irradiance - float3 diffuse = irradiance * ALBEDO; - - float3 F = F_SchlickR(max(dot(N, V), 0.0), F0, roughness); - - // Specular reflectance - float3 specular = reflection * (F * brdf.x + brdf.y); - - // Ambient part - float3 kD = 1.0 - F; - kD *= 1.0 - metallic; - float3 ambient = (kD * diffuse + specular); - - float3 color = ambient + Lo; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap((11.2f).xxx)); - // Gamma correction - color = pow(color, (1.0f / uboParams.gamma).xxx); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/pbribl/pbribl.vert.spv b/shaders/slang/pbribl/pbribl.vert.spv deleted file mode 100644 index 889fb594..00000000 Binary files a/shaders/slang/pbribl/pbribl.vert.spv and /dev/null differ diff --git a/shaders/slang/pbribl/prefilterenvmap.frag.spv b/shaders/slang/pbribl/prefilterenvmap.frag.spv deleted file mode 100644 index 1fc90a68..00000000 Binary files a/shaders/slang/pbribl/prefilterenvmap.frag.spv and /dev/null differ diff --git a/shaders/slang/pbribl/prefilterenvmap.slang b/shaders/slang/pbribl/prefilterenvmap.slang deleted file mode 100644 index d33cd37c..00000000 --- a/shaders/slang/pbribl/prefilterenvmap.slang +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -SamplerCube samplerEnv; - -struct PushConsts { - [[vk::offset(64)]] float roughness; - [[vk::offset(68)]] uint numSamples; -}; -[[vk::push_constant]] PushConsts consts; - -#define PI 3.1415926536 - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(float2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,float2(a,b)); - float sn= fmod(dt,3.14); - return frac(sin(sn) * c); -} - -float2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return float2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -float3 importanceSample_GGX(float2 Xi, float roughness, float3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - float3 up = abs(normal.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); - float3 tangentX = normalize(cross(up, normal)); - float3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Normal Distribution function -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -float3 prefilterEnvMap(float3 R, float roughness) -{ - float3 N = R; - float3 V = R; - float3 color = float3(0.0, 0.0, 0.0); - float totalWeight = 0.0; - int2 envMapDims; - samplerEnv.GetDimensions(envMapDims.x, envMapDims.y); - float envMapDim = float(envMapDims.x); - for(uint i = 0u; i < consts.numSamples; i++) { - float2 Xi = hammersley2d(i, consts.numSamples); - float3 H = importanceSample_GGX(Xi, roughness, N); - float3 L = 2.0 * dot(V, H) * H - V; - float dotNL = clamp(dot(N, L), 0.0, 1.0); - if(dotNL > 0.0) { - // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ - - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotVH = clamp(dot(V, H), 0.0, 1.0); - - // Probability Distribution Function - float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; - // Slid angle of current smple - float omegaS = 1.0 / (float(consts.numSamples) * pdf); - // Solid angle of 1 pixel across all cube faces - float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); - // Biased (+1.0) mip level for better result - float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); - color += samplerEnv.SampleLevel(L, mipLevel).rgb * dotNL; - totalWeight += dotNL; - - } - } - return (color / totalWeight); -} - -[shader("fragment")] -float4 fragmentMain(float3 inPos) -{ - float3 N = normalize(inPos.xyz); - return float4(prefilterEnvMap(N, consts.roughness), 1.0); -} diff --git a/shaders/slang/pbribl/skybox.frag.spv b/shaders/slang/pbribl/skybox.frag.spv deleted file mode 100644 index 84bd3497..00000000 Binary files a/shaders/slang/pbribl/skybox.frag.spv and /dev/null differ diff --git a/shaders/slang/pbribl/skybox.slang b/shaders/slang/pbribl/skybox.slang deleted file mode 100644 index 809fedab..00000000 --- a/shaders/slang/pbribl/skybox.slang +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -ConstantBuffer ubo; - -struct UBOParams { - float4 lights[4]; - float exposure; - float gamma; -}; -ConstantBuffer uboParams; - -SamplerCube samplerEnv; - -// From http://filmicworlds.com/blog/filmic-tonemapping-operators/ -float3 Uncharted2Tonemap(float3 color) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - float W = 11.2; - return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UVW = input.Pos; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 color = samplerEnv.Sample(input.UVW).rgb; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap((11.2f).xxx)); - // Gamma correction - color = pow(color, (1.0f / uboParams.gamma).xxx); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/pbribl/skybox.vert.spv b/shaders/slang/pbribl/skybox.vert.spv deleted file mode 100644 index 57f170e7..00000000 Binary files a/shaders/slang/pbribl/skybox.vert.spv and /dev/null differ diff --git a/shaders/slang/pbrtexture/filtercube.slang b/shaders/slang/pbrtexture/filtercube.slang deleted file mode 100644 index 6c848459..00000000 --- a/shaders/slang/pbrtexture/filtercube.slang +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; -}; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4x4 mvp) -{ - VSOutput output; - output.UVW = input.Pos; - output.Pos = mul(mvp, float4(input.Pos.xyz, 1.0)); - return output; -} diff --git a/shaders/slang/pbrtexture/filtercube.vert.spv b/shaders/slang/pbrtexture/filtercube.vert.spv deleted file mode 100644 index 5d02106a..00000000 Binary files a/shaders/slang/pbrtexture/filtercube.vert.spv and /dev/null differ diff --git a/shaders/slang/pbrtexture/genbrdflut.frag.spv b/shaders/slang/pbrtexture/genbrdflut.frag.spv deleted file mode 100644 index a055c41e..00000000 Binary files a/shaders/slang/pbrtexture/genbrdflut.frag.spv and /dev/null differ diff --git a/shaders/slang/pbrtexture/genbrdflut.slang b/shaders/slang/pbrtexture/genbrdflut.slang deleted file mode 100644 index b40d7b16..00000000 --- a/shaders/slang/pbrtexture/genbrdflut.slang +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - - struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -[[SpecializationConstant]] const uint NUM_SAMPLES = 1024u; - -#define PI 3.1415926536 - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(float2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,float2(a,b)); - float sn= fmod(dt,3.14); - return frac(sin(sn) * c); -} - -float2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return float2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -float3 importanceSample_GGX(float2 Xi, float roughness, float3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - float3 up = abs(normal.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); - float3 tangentX = normalize(cross(up, normal)); - float3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Geometric Shadowing function -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float k = (roughness * roughness) / 2.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -float2 BRDF(float NoV, float roughness) -{ - // Normal always points along z-axis for the 2D lookup - const float3 N = float3(0.0, 0.0, 1.0); - float3 V = float3(sqrt(1.0 - NoV*NoV), 0.0, NoV); - - float2 LUT = float2(0.0, 0.0); - for(uint i = 0u; i < NUM_SAMPLES; i++) { - float2 Xi = hammersley2d(i, NUM_SAMPLES); - float3 H = importanceSample_GGX(Xi, roughness, N); - float3 L = 2.0 * dot(V, H) * H - V; - - float dotNL = max(dot(N, L), 0.0); - float dotNV = max(dot(N, V), 0.0); - float dotVH = max(dot(V, H), 0.0); - float dotNH = max(dot(H, N), 0.0); - - if (dotNL > 0.0) { - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - float G_Vis = (G * dotVH) / (dotNH * dotNV); - float Fc = pow(1.0 - dotVH, 5.0); - LUT += float2((1.0 - Fc) * G_Vis, Fc * G_Vis); - } - } - return LUT / float(NUM_SAMPLES); -} - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(BRDF(input.UV.x, input.UV.y), 0.0, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/pbrtexture/genbrdflut.vert.spv b/shaders/slang/pbrtexture/genbrdflut.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/pbrtexture/genbrdflut.vert.spv and /dev/null differ diff --git a/shaders/slang/pbrtexture/irradiancecube.frag.spv b/shaders/slang/pbrtexture/irradiancecube.frag.spv deleted file mode 100644 index a3dc8bf0..00000000 Binary files a/shaders/slang/pbrtexture/irradiancecube.frag.spv and /dev/null differ diff --git a/shaders/slang/pbrtexture/irradiancecube.slang b/shaders/slang/pbrtexture/irradiancecube.slang deleted file mode 100644 index 31cc96ea..00000000 --- a/shaders/slang/pbrtexture/irradiancecube.slang +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -SamplerCube samplerEnv; - -struct PushConsts { - [[vk::offset(64)]] float deltaPhi; - [[vk::offset(68)]] float deltaTheta; -}; -[[vk::push_constant]] PushConsts consts; - -#define PI 3.1415926535897932384626433832795 - -[shader("fragment")] -float4 fragmentMain(float3 inPos) -{ - float3 N = normalize(inPos.xyz); - float3 up = float3(0.0, 1.0, 0.0); - float3 right = normalize(cross(up, N)); - up = cross(N, right); - - const float TWO_PI = PI * 2.0; - const float HALF_PI = PI * 0.5; - - float3 color = float3(0.0, 0.0, 0.0); - uint sampleCount = 0u; - for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) { - for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) { - float3 tempVec = cos(phi) * right + sin(phi) * up; - float3 sampleVector = cos(theta) * N + sin(theta) * tempVec; - color += samplerEnv.Sample(sampleVector).rgb * cos(theta) * sin(theta); - sampleCount++; - } - } - return float4(PI * color / float(sampleCount), 1.0); -} diff --git a/shaders/slang/pbrtexture/pbrtexture.frag.spv b/shaders/slang/pbrtexture/pbrtexture.frag.spv deleted file mode 100644 index 7c56a77a..00000000 Binary files a/shaders/slang/pbrtexture/pbrtexture.frag.spv and /dev/null differ diff --git a/shaders/slang/pbrtexture/pbrtexture.slang b/shaders/slang/pbrtexture/pbrtexture.slang deleted file mode 100644 index 0d7bbef0..00000000 --- a/shaders/slang/pbrtexture/pbrtexture.slang +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2020 Google LLC - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float4 Tangent; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 WorldPos; - float3 Normal; - float2 UV; - float3 Tangent; -}; - -struct UBO { - float4x4 projection; - float4x4 model; - float4x4 view; - float3 camPos; -}; -ConstantBuffer ubo; - -struct UBOParams { - float4 lights[4]; - float exposure; - float gamma; -}; -ConstantBuffer uboParams; - -SamplerCube samplerIrradiance; -Sampler2D samplerBRDFLUT; -SamplerCube prefilteredMapSampler; - -Sampler2D albedoMapSampler; -Sampler2D normalMapSampler; -Sampler2D aoMapSampler; -Sampler2D metallicMapSampler; -Sampler2D roughnessMapSampler; - -#define PI 3.1415926535897932384626433832795 -#define ALBEDO(uv) pow(albedoMapSampler.Sample(uv).rgb, float3(2.2, 2.2, 2.2)) - -// From http://filmicgames.com/archives/75 -float3 Uncharted2Tonemap(float3 x) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F; -} - -// Normal Distribution function -------------------------------------- -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -// Geometric Shadowing function -------------------------------------- -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; -} - -// Fresnel function ---------------------------------------------------- -float3 F_Schlick(float cosTheta, float3 F0) -{ - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} -float3 F_SchlickR(float cosTheta, float3 F0, float roughness) -{ - return F0 + (max((1.0 - roughness).xxx, F0) - F0) * pow(1.0 - cosTheta, 5.0); -} - -float3 prefilteredReflection(float3 R, float roughness) -{ - const float MAX_REFLECTION_LOD = 9.0; // todo: param/const - float lod = roughness * MAX_REFLECTION_LOD; - float lodf = floor(lod); - float lodc = ceil(lod); - float3 a = prefilteredMapSampler.SampleLevel(R, lodf).rgb; - float3 b = prefilteredMapSampler.SampleLevel(R, lodc).rgb; - return lerp(a, b, lod - lodf); -} - -float3 specularContribution(float2 inUV, float3 L, float3 V, float3 N, float3 F0, float metallic, float roughness) -{ - // Precalculate vectors and dot products - float3 H = normalize (V + L); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - - // Light color fixed - float3 lightColor = float3(1.0, 1.0, 1.0); - - float3 color = float3(0.0, 0.0, 0.0); - - if (dotNL > 0.0) { - // D = Normal distribution (Distribution of the microfacets) - float D = D_GGX(dotNH, roughness); - // G = Geometric shadowing term (Microfacets shadowing) - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - // F = Fresnel factor (Reflectance depending on angle of incidence) - float3 F = F_Schlick(dotNV, F0); - float3 spec = D * F * G / (4.0 * dotNL * dotNV + 0.001); - float3 kD = (float3(1.0, 1.0, 1.0) - F) * (1.0 - metallic); - color += (kD * ALBEDO(inUV) / PI + spec) * dotNL; - } - - return color; -} - -float3 calculateNormal(VSOutput input) -{ - float3 tangentNormal = normalMapSampler.Sample(input.UV).xyz * 2.0 - 1.0; - - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent); - float3 B = normalize(cross(N, T)); - float3x3 TBN = transpose(float3x3(T, B, N)); - - return normalize(mul(TBN, tangentNormal)); -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - float3 locPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.WorldPos = locPos; - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.Tangent = mul((float3x3)ubo.model, input.Tangent.xyz); - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.view, float4(output.WorldPos, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = calculateNormal(input); - float3 V = normalize(ubo.camPos - input.WorldPos); - float3 R = reflect(-V, N); - - float metallic = metallicMapSampler.Sample(input.UV).r; - float roughness = roughnessMapSampler.Sample(input.UV).r; - - float3 F0 = float3(0.04, 0.04, 0.04); - F0 = lerp(F0, ALBEDO(input.UV), metallic); - - float3 Lo = float3(0.0, 0.0, 0.0); - for(int i = 0; i < 4; i++) { - float3 L = normalize(uboParams.lights[i].xyz - input.WorldPos); - Lo += specularContribution(input.UV, L, V, N, F0, metallic, roughness); - } - - float2 brdf = samplerBRDFLUT.Sample(float2(max(dot(N, V), 0.0), roughness)).rg; - float3 reflection = prefilteredReflection(R, roughness).rgb; - float3 irradiance = samplerIrradiance.Sample(N).rgb; - - // Diffuse based on irradiance - float3 diffuse = irradiance * ALBEDO(input.UV); - - float3 F = F_SchlickR(max(dot(N, V), 0.0), F0, roughness); - - // Specular reflectance - float3 specular = reflection * (F * brdf.x + brdf.y); - - // Ambient part - float3 kD = 1.0 - F; - kD *= 1.0 - metallic; - float3 ambient = (kD * diffuse + specular) * aoMapSampler.Sample(input.UV).rrr; - - float3 color = ambient + Lo; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap((11.2f).xxx)); - // Gamma correction - color = pow(color, (1.0f / uboParams.gamma).xxx); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/pbrtexture/pbrtexture.vert.spv b/shaders/slang/pbrtexture/pbrtexture.vert.spv deleted file mode 100644 index b56bda1c..00000000 Binary files a/shaders/slang/pbrtexture/pbrtexture.vert.spv and /dev/null differ diff --git a/shaders/slang/pbrtexture/prefilterenvmap.frag.spv b/shaders/slang/pbrtexture/prefilterenvmap.frag.spv deleted file mode 100644 index 1fc90a68..00000000 Binary files a/shaders/slang/pbrtexture/prefilterenvmap.frag.spv and /dev/null differ diff --git a/shaders/slang/pbrtexture/prefilterenvmap.slang b/shaders/slang/pbrtexture/prefilterenvmap.slang deleted file mode 100644 index d33cd37c..00000000 --- a/shaders/slang/pbrtexture/prefilterenvmap.slang +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -SamplerCube samplerEnv; - -struct PushConsts { - [[vk::offset(64)]] float roughness; - [[vk::offset(68)]] uint numSamples; -}; -[[vk::push_constant]] PushConsts consts; - -#define PI 3.1415926536 - -// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -float random(float2 co) -{ - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,float2(a,b)); - float sn= fmod(dt,3.14); - return frac(sin(sn) * c); -} - -float2 hammersley2d(uint i, uint N) -{ - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return float2(float(i) /float(N), rdi); -} - -// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -float3 importanceSample_GGX(float2 Xi, float roughness, float3 normal) -{ - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - float3 up = abs(normal.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); - float3 tangentX = normalize(cross(up, normal)); - float3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); -} - -// Normal Distribution function -float D_GGX(float dotNH, float roughness) -{ - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); -} - -float3 prefilterEnvMap(float3 R, float roughness) -{ - float3 N = R; - float3 V = R; - float3 color = float3(0.0, 0.0, 0.0); - float totalWeight = 0.0; - int2 envMapDims; - samplerEnv.GetDimensions(envMapDims.x, envMapDims.y); - float envMapDim = float(envMapDims.x); - for(uint i = 0u; i < consts.numSamples; i++) { - float2 Xi = hammersley2d(i, consts.numSamples); - float3 H = importanceSample_GGX(Xi, roughness, N); - float3 L = 2.0 * dot(V, H) * H - V; - float dotNL = clamp(dot(N, L), 0.0, 1.0); - if(dotNL > 0.0) { - // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ - - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotVH = clamp(dot(V, H), 0.0, 1.0); - - // Probability Distribution Function - float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; - // Slid angle of current smple - float omegaS = 1.0 / (float(consts.numSamples) * pdf); - // Solid angle of 1 pixel across all cube faces - float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); - // Biased (+1.0) mip level for better result - float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); - color += samplerEnv.SampleLevel(L, mipLevel).rgb * dotNL; - totalWeight += dotNL; - - } - } - return (color / totalWeight); -} - -[shader("fragment")] -float4 fragmentMain(float3 inPos) -{ - float3 N = normalize(inPos.xyz); - return float4(prefilterEnvMap(N, consts.roughness), 1.0); -} diff --git a/shaders/slang/pbrtexture/skybox.frag.spv b/shaders/slang/pbrtexture/skybox.frag.spv deleted file mode 100644 index 84bd3497..00000000 Binary files a/shaders/slang/pbrtexture/skybox.frag.spv and /dev/null differ diff --git a/shaders/slang/pbrtexture/skybox.slang b/shaders/slang/pbrtexture/skybox.slang deleted file mode 100644 index 809fedab..00000000 --- a/shaders/slang/pbrtexture/skybox.slang +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -ConstantBuffer ubo; - -struct UBOParams { - float4 lights[4]; - float exposure; - float gamma; -}; -ConstantBuffer uboParams; - -SamplerCube samplerEnv; - -// From http://filmicworlds.com/blog/filmic-tonemapping-operators/ -float3 Uncharted2Tonemap(float3 color) -{ - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - float W = 11.2; - return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UVW = input.Pos; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 color = samplerEnv.Sample(input.UVW).rgb; - - // Tone mapping - color = Uncharted2Tonemap(color * uboParams.exposure); - color = color * (1.0f / Uncharted2Tonemap((11.2f).xxx)); - // Gamma correction - color = pow(color, (1.0f / uboParams.gamma).xxx); - - return float4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/pbrtexture/skybox.vert.spv b/shaders/slang/pbrtexture/skybox.vert.spv deleted file mode 100644 index 57f170e7..00000000 Binary files a/shaders/slang/pbrtexture/skybox.vert.spv and /dev/null differ diff --git a/shaders/slang/pipelines/phong.frag.spv b/shaders/slang/pipelines/phong.frag.spv deleted file mode 100644 index 37d29241..00000000 Binary files a/shaders/slang/pipelines/phong.frag.spv and /dev/null differ diff --git a/shaders/slang/pipelines/phong.slang b/shaders/slang/pipelines/phong.slang deleted file mode 100644 index e6e6f172..00000000 --- a/shaders/slang/pipelines/phong.slang +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Desaturate color - float3 color = lerp(input.Color, dot(float3(0.2126,0.7152,0.0722), input.Color).xxx, 0.65); - - // High ambient colors because mesh materials are pretty dark - float3 ambient = color * float3(1.0, 1.0, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color; - float3 specular = pow(max(dot(R, V), 0.0), 32.0) * float3(0.35, 0.35, 0.35); - return float4(ambient + diffuse * 1.75 + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/pipelines/phong.vert.spv b/shaders/slang/pipelines/phong.vert.spv deleted file mode 100644 index c5f07810..00000000 Binary files a/shaders/slang/pipelines/phong.vert.spv and /dev/null differ diff --git a/shaders/slang/pipelines/toon.frag.spv b/shaders/slang/pipelines/toon.frag.spv deleted file mode 100644 index d2367292..00000000 Binary files a/shaders/slang/pipelines/toon.frag.spv and /dev/null differ diff --git a/shaders/slang/pipelines/toon.slang b/shaders/slang/pipelines/toon.slang deleted file mode 100644 index 14cc13e5..00000000 --- a/shaders/slang/pipelines/toon.slang +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Desaturate color - float3 color = lerp(input.Color, dot(float3(0.2126,0.7152,0.0722), input.Color).xxx, 0.65); - - // High ambient colors because mesh materials are pretty dark - float3 ambient = color * float3(1.0, 1.0, 1.0); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color; - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - - float intensity = dot(N,L); - float shade = 1.0; - shade = intensity < 0.5 ? 0.75 : shade; - shade = intensity < 0.35 ? 0.6 : shade; - shade = intensity < 0.25 ? 0.5 : shade; - shade = intensity < 0.1 ? 0.25 : shade; - - return float4(input.Color * 3.0 * shade, 1); -} \ No newline at end of file diff --git a/shaders/slang/pipelines/toon.vert.spv b/shaders/slang/pipelines/toon.vert.spv deleted file mode 100644 index c5f07810..00000000 Binary files a/shaders/slang/pipelines/toon.vert.spv and /dev/null differ diff --git a/shaders/slang/pipelines/wireframe.frag.spv b/shaders/slang/pipelines/wireframe.frag.spv deleted file mode 100644 index 649fef4c..00000000 Binary files a/shaders/slang/pipelines/wireframe.frag.spv and /dev/null differ diff --git a/shaders/slang/pipelines/wireframe.slang b/shaders/slang/pipelines/wireframe.slang deleted file mode 100644 index 4482be10..00000000 --- a/shaders/slang/pipelines/wireframe.slang +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, input.Pos)); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(input.Color * 1.5, 1); -} \ No newline at end of file diff --git a/shaders/slang/pipelines/wireframe.vert.spv b/shaders/slang/pipelines/wireframe.vert.spv deleted file mode 100644 index 4232d9dd..00000000 Binary files a/shaders/slang/pipelines/wireframe.vert.spv and /dev/null differ diff --git a/shaders/slang/pipelinestatistics/scene.frag.spv b/shaders/slang/pipelinestatistics/scene.frag.spv deleted file mode 100644 index 3191b732..00000000 Binary files a/shaders/slang/pipelinestatistics/scene.frag.spv and /dev/null differ diff --git a/shaders/slang/pipelinestatistics/scene.slang b/shaders/slang/pipelinestatistics/scene.slang deleted file mode 100644 index 781f7f7f..00000000 --- a/shaders/slang/pipelinestatistics/scene.slang +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct HSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct DSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner[2] : SV_InsideTessFactor; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; -}; -ConstantBuffer ubo; - -struct PushConsts { - float3 objPos; -}; -[[vk::push_constant]] PushConsts pushConsts; - -ConstantsHSOutput ConstantsHS(InputPatch patch) -{ - ConstantsHSOutput output; - output.TessLevelInner[0] = 2.0; - output.TessLevelInner[1] = 2.0; - output.TessLevelOuter[0] = 1.0; - output.TessLevelOuter[1] = 1.0; - output.TessLevelOuter[2] = 1.0; - return output; -} - -[shader("hull")] -[domain("tri")] -[partitioning("integer")] -[outputtopology("triangle_ccw")] -[outputcontrolpoints(3)] -[patchconstantfunc("ConstantsHS")] -[maxtessfactor(20.0f)] -HSOutput hullMain(InputPatch patch, uint InvocationID: SV_OutputControlPointID) -{ - HSOutput output; - output.Pos = patch[InvocationID].Pos; - output.Normal = patch[InvocationID].Normal; - output.Color = patch[InvocationID].Color; - output.ViewVec = patch[InvocationID].ViewVec; - output.LightVec = patch[InvocationID].LightVec; - return output; -} - -[shader("domain")] -[domain("tri")] -DSOutput domainMain(ConstantsHSOutput input, float3 TessCoord: SV_DomainLocation, const OutputPatch patch) -{ - DSOutput output; - output.Pos = (TessCoord.x * patch[2].Pos) + (TessCoord.y * patch[1].Pos) + (TessCoord.z * patch[0].Pos); - output.Normal = TessCoord.x * patch[2].Normal + TessCoord.y * patch[1].Normal + TessCoord.z * patch[0].Normal; - output.ViewVec = TessCoord.x * patch[2].ViewVec + TessCoord.y * patch[1].ViewVec + TessCoord.z * patch[0].ViewVec; - output.LightVec = TessCoord.x * patch[2].LightVec + TessCoord.y * patch[1].LightVec + TessCoord.z * patch[0].LightVec; - output.Color = patch[0].Color; - return output; -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - float3 locPos = mul(ubo.modelview, float4(input.Pos, 1.0)).xyz; - float3 worldPos = mul(ubo.modelview, float4(input.Pos + pushConsts.objPos, 1.0)).xyz; - output.Pos = mul(ubo.projection, float4(worldPos, 1.0)); - float4 pos = mul(ubo.modelview, float4(worldPos, 1.0)); - output.Normal = mul((float3x3)ubo.modelview, input.Normal); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.75, 0.75, 0.75); - return float4(diffuse + specular, 0.5); -} \ No newline at end of file diff --git a/shaders/slang/pipelinestatistics/scene.tesc.spv b/shaders/slang/pipelinestatistics/scene.tesc.spv deleted file mode 100644 index 321b6d58..00000000 Binary files a/shaders/slang/pipelinestatistics/scene.tesc.spv and /dev/null differ diff --git a/shaders/slang/pipelinestatistics/scene.tese.spv b/shaders/slang/pipelinestatistics/scene.tese.spv deleted file mode 100644 index 06ca6acf..00000000 Binary files a/shaders/slang/pipelinestatistics/scene.tese.spv and /dev/null differ diff --git a/shaders/slang/pipelinestatistics/scene.vert.spv b/shaders/slang/pipelinestatistics/scene.vert.spv deleted file mode 100644 index 019aef42..00000000 Binary files a/shaders/slang/pipelinestatistics/scene.vert.spv and /dev/null differ diff --git a/shaders/slang/pushconstants/pushconstants.frag.spv b/shaders/slang/pushconstants/pushconstants.frag.spv deleted file mode 100644 index 81761f27..00000000 Binary files a/shaders/slang/pushconstants/pushconstants.frag.spv and /dev/null differ diff --git a/shaders/slang/pushconstants/pushconstants.slang b/shaders/slang/pushconstants/pushconstants.slang deleted file mode 100644 index 8b318b88..00000000 --- a/shaders/slang/pushconstants/pushconstants.slang +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos : POSITION0; - float3 Normal; - float3 Color; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; -}; -ConstantBuffer ubo; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; -}; - -// Uniform entry-point parameters are automatically bound to push constants by slang -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4 pushColor, uniform float4 pushPosition) -{ - VSOutput output; - output.Color = input.Color * pushColor.rgb; - float3 locPos = float3(mul(ubo.model, float4(input.Pos.xyz, 1.0)).xyz); - float3 worldPos = locPos + pushPosition.xyz; - output.Pos = mul(ubo.projection, mul(ubo.view, float4(worldPos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/pushconstants/pushconstants.vert.spv b/shaders/slang/pushconstants/pushconstants.vert.spv deleted file mode 100644 index cebd2a2f..00000000 Binary files a/shaders/slang/pushconstants/pushconstants.vert.spv and /dev/null differ diff --git a/shaders/slang/pushdescriptors/cube.frag.spv b/shaders/slang/pushdescriptors/cube.frag.spv deleted file mode 100644 index 26d7f3dc..00000000 Binary files a/shaders/slang/pushdescriptors/cube.frag.spv and /dev/null differ diff --git a/shaders/slang/pushdescriptors/cube.slang b/shaders/slang/pushdescriptors/cube.slang deleted file mode 100644 index 372c5eaa..00000000 --- a/shaders/slang/pushdescriptors/cube.slang +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; -}; - -struct UBOCamera { - float4x4 projection; - float4x4 view; -}; -ConstantBuffer uboCamera; - -struct UBOModel { - float4x4 local; -}; -ConstantBuffer uboModel; - -Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(uboCamera.projection, mul(uboCamera.view, mul(uboModel.local, float4(input.Pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/pushdescriptors/cube.vert.spv b/shaders/slang/pushdescriptors/cube.vert.spv deleted file mode 100644 index fe201558..00000000 Binary files a/shaders/slang/pushdescriptors/cube.vert.spv and /dev/null differ diff --git a/shaders/slang/radialblur/colorpass.frag.spv b/shaders/slang/radialblur/colorpass.frag.spv deleted file mode 100644 index 137bb8aa..00000000 Binary files a/shaders/slang/radialblur/colorpass.frag.spv and /dev/null differ diff --git a/shaders/slang/radialblur/colorpass.slang b/shaders/slang/radialblur/colorpass.slang deleted file mode 100644 index c36de69e..00000000 --- a/shaders/slang/radialblur/colorpass.slang +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float gradientPos; -}; -ConstantBuffer ubo; - -Sampler2D samplerGradientRamp; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.UV = float2(ubo.gradientPos, 0.0f); - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Use max. color channel value to detect bright glow emitters - if ((input.Color.r >= 0.9) || (input.Color.g >= 0.9) || (input.Color.b >= 0.9)) - { - return float4(samplerGradientRamp.Sample(input.UV).rgb, 1); - } else { - return float4(input.Color, 1); - } -} \ No newline at end of file diff --git a/shaders/slang/radialblur/colorpass.vert.spv b/shaders/slang/radialblur/colorpass.vert.spv deleted file mode 100644 index a99056dc..00000000 Binary files a/shaders/slang/radialblur/colorpass.vert.spv and /dev/null differ diff --git a/shaders/slang/radialblur/phongpass.frag.spv b/shaders/slang/radialblur/phongpass.frag.spv deleted file mode 100644 index d975a832..00000000 Binary files a/shaders/slang/radialblur/phongpass.frag.spv and /dev/null differ diff --git a/shaders/slang/radialblur/phongpass.slang b/shaders/slang/radialblur/phongpass.slang deleted file mode 100644 index 7569146d..00000000 --- a/shaders/slang/radialblur/phongpass.slang +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float2 UV; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 EyePos; - float3 LightVec; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float gradientPos; -}; -ConstantBuffer ubo; - -Sampler2D samplerGradientRamp; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = float2(ubo.gradientPos, 0.0); - output.Pos = mul(ubo.projection, mul(ubo.model, input.Pos)); - output.EyePos = mul(ubo.model, input.Pos).xyz; - float4 lightPos = float4(0.0, 0.0, -5.0, 1.0); // * ubo.model; - output.LightVec = normalize(lightPos.xyz - input.Pos.xyz); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // No light calculations for glow color - // Use max. color channel value - // to detect bright glow emitters - if ((input.Color.r >= 0.9) || (input.Color.g >= 0.9) || (input.Color.b >= 0.9)) - { - return float4(samplerGradientRamp.Sample(input.UV).rgb, 1); - } else { - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - float4 IAmbient = float4(0.2, 0.2, 0.2, 1.0); - float4 IDiffuse = float4(0.5, 0.5, 0.5, 0.5) * max(dot(input.Normal, input.LightVec), 0.0); - float specular = 0.25; - float4 ISpecular = float4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 4.0) * specular; - return float4((IAmbient + IDiffuse) * float4(input.Color, 1.0) + ISpecular); - } -} \ No newline at end of file diff --git a/shaders/slang/radialblur/phongpass.vert.spv b/shaders/slang/radialblur/phongpass.vert.spv deleted file mode 100644 index 65c33a6d..00000000 Binary files a/shaders/slang/radialblur/phongpass.vert.spv and /dev/null differ diff --git a/shaders/slang/radialblur/radialblur.frag.spv b/shaders/slang/radialblur/radialblur.frag.spv deleted file mode 100644 index 26486d4a..00000000 Binary files a/shaders/slang/radialblur/radialblur.frag.spv and /dev/null differ diff --git a/shaders/slang/radialblur/radialblur.slang b/shaders/slang/radialblur/radialblur.slang deleted file mode 100644 index 8fefdf16..00000000 --- a/shaders/slang/radialblur/radialblur.slang +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -struct UBO -{ - float radialBlurScale; - float radialBlurStrength; - float2 radialOrigin; -}; -ConstantBuffer ubo; - -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - int2 texDim; - samplerColor.GetDimensions(texDim.x, texDim.y); - float2 radialSize = float2(1.0 / texDim.x, 1.0 / texDim.y); - float2 UV = input.UV; - float4 color = float4(0.0, 0.0, 0.0, 0.0); - UV += radialSize * 0.5 - ubo.radialOrigin; - #define samples 32 - for (int i = 0; i < samples; i++) - { - float scale = 1.0 - ubo.radialBlurScale * (float(i) / float(samples - 1)); - color += samplerColor.Sample(UV * scale + ubo.radialOrigin); - } - return (color / samples) * ubo.radialBlurStrength; -} \ No newline at end of file diff --git a/shaders/slang/radialblur/radialblur.vert.spv b/shaders/slang/radialblur/radialblur.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/radialblur/radialblur.vert.spv and /dev/null differ diff --git a/shaders/slang/rayquery/scene.frag.spv b/shaders/slang/rayquery/scene.frag.spv deleted file mode 100644 index 24fea2a3..00000000 Binary files a/shaders/slang/rayquery/scene.frag.spv and /dev/null differ diff --git a/shaders/slang/rayquery/scene.slang b/shaders/slang/rayquery/scene.slang deleted file mode 100644 index 5b061c62..00000000 --- a/shaders/slang/rayquery/scene.slang +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Color; - float3 Normal; -} - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; - float3 WorldPos; -} - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float3 lightPos; -}; -ConstantBuffer ubo; - -RaytracingAccelerationStructure accelStruct; - -#define ambient 0.1 - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.WorldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - output.LightVec = normalize(ubo.lightPos - input.Pos); - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = normalize(-reflect(L, N)); - float3 diffuse = max(dot(N, L), ambient) * input.Color; - - float4 color = float4(diffuse, 1.0); - - RayDesc rayDesc; - rayDesc.Origin = input.WorldPos; - rayDesc.Direction = L; - rayDesc.TMin = 0.01; - rayDesc.TMax = 1000.0; - - RayQuery rayQuery; - rayQuery.TraceRayInline(accelStruct, RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, 0xFF, rayDesc); - - // Traverse the acceleration structure and store information about the first intersection (if any) - rayQuery.Proceed(); - - // If the intersection has hit a triangle, the fragment is shadowed - if (rayQuery.CommittedStatus() == COMMITTED_TRIANGLE_HIT) { - color *= 0.1; - } - - return color; -} diff --git a/shaders/slang/rayquery/scene.vert.spv b/shaders/slang/rayquery/scene.vert.spv deleted file mode 100644 index 86b91b87..00000000 Binary files a/shaders/slang/rayquery/scene.vert.spv and /dev/null differ diff --git a/shaders/slang/raytracingbasic/closesthit.rchit.spv b/shaders/slang/raytracingbasic/closesthit.rchit.spv deleted file mode 100644 index dbc3087b..00000000 Binary files a/shaders/slang/raytracingbasic/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/slang/raytracingbasic/miss.rmiss.spv b/shaders/slang/raytracingbasic/miss.rmiss.spv deleted file mode 100644 index 8d1e7b12..00000000 Binary files a/shaders/slang/raytracingbasic/miss.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracingbasic/raygen.rgen.spv b/shaders/slang/raytracingbasic/raygen.rgen.spv deleted file mode 100644 index 84a72044..00000000 Binary files a/shaders/slang/raytracingbasic/raygen.rgen.spv and /dev/null differ diff --git a/shaders/slang/raytracingbasic/raytracingbasic.slang b/shaders/slang/raytracingbasic/raytracingbasic.slang deleted file mode 100644 index 49d8182d..00000000 --- a/shaders/slang/raytracingbasic/raytracingbasic.slang +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -RaytracingAccelerationStructure accelStruct; -RWTexture2D image; -struct CameraProperties -{ - float4x4 viewInverse; - float4x4 projInverse; -}; -ConstantBuffer cam; - -struct Attributes -{ - float2 bary; -}; - -struct Payload -{ - float3 hitValue; -}; - -[shader("raygeneration")] -void raygenerationMain() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter/float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0,0,0,1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - TraceRay(accelStruct, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} - -[shader("closesthit")] -void closesthitMain(inout Payload p, in Attributes attribs) -{ - const float3 barycentricCoords = float3(1.0f - attribs.bary.x - attribs.bary.y, attribs.bary.x, attribs.bary.y); - p.hitValue = barycentricCoords; -} - -[shader("miss")] -void missMain(inout Payload p) -{ - p.hitValue = float3(0.0, 0.0, 0.2); -} diff --git a/shaders/slang/raytracingcallable/callable1.rcall.spv b/shaders/slang/raytracingcallable/callable1.rcall.spv deleted file mode 100644 index c9709d8f..00000000 Binary files a/shaders/slang/raytracingcallable/callable1.rcall.spv and /dev/null differ diff --git a/shaders/slang/raytracingcallable/callable1.slang b/shaders/slang/raytracingcallable/callable1.slang deleted file mode 100644 index afacce9a..00000000 --- a/shaders/slang/raytracingcallable/callable1.slang +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -[shader("callable")] -void callableMain(inout float3 outColor) -{ - // Generate a checker board pattern - float2 pos = float2(DispatchRaysIndex().x / 8, DispatchRaysIndex().y / 8); - float col = (pos.x + (pos.y % 2.0)) % 2.0; - outColor = float3(col, col, col); -} \ No newline at end of file diff --git a/shaders/slang/raytracingcallable/callable2.rcall.spv b/shaders/slang/raytracingcallable/callable2.rcall.spv deleted file mode 100644 index 282018ee..00000000 Binary files a/shaders/slang/raytracingcallable/callable2.rcall.spv and /dev/null differ diff --git a/shaders/slang/raytracingcallable/callable2.slang b/shaders/slang/raytracingcallable/callable2.slang deleted file mode 100644 index de51b24d..00000000 --- a/shaders/slang/raytracingcallable/callable2.slang +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -[shader("callable")] -void callableMain(inout float3 outColor) -{ - outColor = float3(0.0, 1.0, 0.0); -} \ No newline at end of file diff --git a/shaders/slang/raytracingcallable/callable3.rcall.spv b/shaders/slang/raytracingcallable/callable3.rcall.spv deleted file mode 100644 index fa818478..00000000 Binary files a/shaders/slang/raytracingcallable/callable3.rcall.spv and /dev/null differ diff --git a/shaders/slang/raytracingcallable/callable3.slang b/shaders/slang/raytracingcallable/callable3.slang deleted file mode 100644 index 75ca336a..00000000 --- a/shaders/slang/raytracingcallable/callable3.slang +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -[shader("callable")] -void callableMain(inout float3 outColor) -{ - // Generate a checker board pattern - float2 pos = float2(DispatchRaysIndex().x / 8, DispatchRaysIndex().y / 8); - float col = pos.y % 2.0; - outColor = float3(col, col, col); -} \ No newline at end of file diff --git a/shaders/slang/raytracingcallable/closesthit.rchit.spv b/shaders/slang/raytracingcallable/closesthit.rchit.spv deleted file mode 100644 index 17922e44..00000000 Binary files a/shaders/slang/raytracingcallable/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/slang/raytracingcallable/miss.rmiss.spv b/shaders/slang/raytracingcallable/miss.rmiss.spv deleted file mode 100644 index 8d1e7b12..00000000 Binary files a/shaders/slang/raytracingcallable/miss.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracingcallable/raygen.rgen.spv b/shaders/slang/raytracingcallable/raygen.rgen.spv deleted file mode 100644 index 84a72044..00000000 Binary files a/shaders/slang/raytracingcallable/raygen.rgen.spv and /dev/null differ diff --git a/shaders/slang/raytracingcallable/raytracingcallable.slang b/shaders/slang/raytracingcallable/raytracingcallable.slang deleted file mode 100644 index e125f455..00000000 --- a/shaders/slang/raytracingcallable/raytracingcallable.slang +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -RaytracingAccelerationStructure accelStruct; -RWTexture2D image; -struct CameraProperties -{ - float4x4 viewInverse; - float4x4 projInverse; -}; -ConstantBuffer cam; - -struct Payload -{ - float3 hitValue; -}; - -struct CallData -{ - float3 outColor; -}; - -struct Attributes -{ - float2 bary; -}; - -[shader("raygeneration")] -void raygenerationMain() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter / float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0, 0, 0, 1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - TraceRay(accelStruct, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} - -[shader("closesthit")] -void closesthitMain(inout Payload p, in Attributes attribs) -{ - // Execute the callable shader indexed by the current geometry being hit - // For our sample this means that the first callable shader in the SBT is invoked for the first triangle, the second callable shader for the second triangle, etc. - CallData callData; - CallShader(GeometryIndex(), callData); - p.hitValue = callData.outColor; -} - -[shader("miss")] -void missMain(inout Payload p) -{ - p.hitValue = float3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/slang/raytracinggltf/anyhit.rahit.spv b/shaders/slang/raytracinggltf/anyhit.rahit.spv deleted file mode 100644 index 1d38b30b..00000000 Binary files a/shaders/slang/raytracinggltf/anyhit.rahit.spv and /dev/null differ diff --git a/shaders/slang/raytracinggltf/closesthit.rchit.spv b/shaders/slang/raytracinggltf/closesthit.rchit.spv deleted file mode 100644 index 9499a6ed..00000000 Binary files a/shaders/slang/raytracinggltf/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/slang/raytracinggltf/miss.rmiss.spv b/shaders/slang/raytracinggltf/miss.rmiss.spv deleted file mode 100644 index d35423b7..00000000 Binary files a/shaders/slang/raytracinggltf/miss.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracinggltf/raygen.rgen.spv b/shaders/slang/raytracinggltf/raygen.rgen.spv deleted file mode 100644 index 1f69b26c..00000000 Binary files a/shaders/slang/raytracinggltf/raygen.rgen.spv and /dev/null differ diff --git a/shaders/slang/raytracinggltf/raytracinggltf.slang b/shaders/slang/raytracinggltf/raytracinggltf.slang deleted file mode 100644 index 76f2a832..00000000 --- a/shaders/slang/raytracinggltf/raytracinggltf.slang +++ /dev/null @@ -1,219 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Payload -{ - float3 hitValue; - uint payloadSeed; - bool shadowed; -}; - -struct GeometryNode { - ConstBufferPointer vertices; - ConstBufferPointer indices; - int textureIndexBaseColor; - int textureIndexOcclusion; -}; - -struct UBOCameraProperties { - float4x4 viewInverse; - float4x4 projInverse; - uint frame; -} - -[[vk::binding(0, 0)]] RaytracingAccelerationStructure accelStruct; -[[vk::binding(1, 0)]] RWTexture2D image; -[[vk::binding(2, 0)]] ConstantBuffer cam; -[[vk::binding(4, 0)]] StructuredBuffer geometryNodes; -[[vk::binding(5, 0)]] Sampler2D textures[]; - -struct Vertex -{ - float3 pos; - float3 normal; - float2 uv; -}; - -struct Triangle { - Vertex vertices[3]; - float3 normal; - float2 uv; -}; - -struct Attributes -{ - float2 bary; -}; - -// Tiny Encryption Algorithm -// By Fahad Zafar, Marc Olano and Aaron Curtis, see https://www.highperformancegraphics.org/previous/www_2010/media/GPUAlgorithms/HPG2010_GPUAlgorithms_Zafar.pdf -uint tea(uint val0, uint val1) -{ - uint sum = 0; - uint v0 = val0; - uint v1 = val1; - for (uint n = 0; n < 16; n++) - { - sum += 0x9E3779B9; - v0 += ((v1 << 4) + 0xA341316C) ^ (v1 + sum) ^ ((v1 >> 5) + 0xC8013EA4); - v1 += ((v0 << 4) + 0xAD90777D) ^ (v0 + sum) ^ ((v0 >> 5) + 0x7E95761E); - } - return v0; -} - -// Linear congruential generator based on the previous RNG state -// See https://en.wikipedia.org/wiki/Linear_congruential_generator -uint lcg(inout uint previous) -{ - const uint multiplier = 1664525u; - const uint increment = 1013904223u; - previous = (multiplier * previous + increment); - return previous & 0x00FFFFFF; -} - -// Generate a random float in [0, 1) given the previous RNG state -float rnd(inout uint previous) -{ - return (float(lcg(previous)) / float(0x01000000)); -} - -// This function will unpack our vertex buffer data into a single triangle and calculates uv coordinates -Triangle unpackTriangle(uint index, Attributes attribs) { - Triangle tri; - const uint triIndex = index * 3; - const uint vertexsize = 112; - - GeometryNode geometryNode = geometryNodes[GeometryIndex()]; - - // Indices indices = Indices(geometryNode.indexBufferDeviceAddress); - // Vertices vertices = Vertices(geometryNode.vertexBufferDeviceAddress); - - // Unpack vertices - // Data is packed as float4 so we can map to the glTF vertex structure from the host side - // We match vkglTF::Vertex: pos.xyz+normal.x, normalyz+uv.xy - // glm::float3 pos; - // glm::float3 normal; - // glm::float2 uv; - // ... - for (uint i = 0; i < 3; i++) { - const uint offset = geometryNode.indices[triIndex + i] * 6; - float4 d0 = geometryNode.vertices[offset + 0]; // pos.xyz, n.x - float4 d1 = geometryNode.vertices[offset + 1]; // n.yz, uv.xy - tri.vertices[i].pos = d0.xyz; - tri.vertices[i].normal = float3(d0.w, d1.xy); - tri.vertices[i].uv = float2(d1.z, d1.w); - } - // Calculate values at barycentric coordinates - float3 barycentricCoords = float3(1.0f - attribs.bary.x - attribs.bary.y, attribs.bary.x, attribs.bary.y); - tri.uv = tri.vertices[0].uv * barycentricCoords.x + tri.vertices[1].uv * barycentricCoords.y + tri.vertices[2].uv * barycentricCoords.z; - tri.normal = tri.vertices[0].normal * barycentricCoords.x + tri.vertices[1].normal * barycentricCoords.y + tri.vertices[2].normal * barycentricCoords.z; - return tri; -} - -[shader("raygeneration")] -void raygenerationMain() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - uint seed = tea(LaunchID.y * LaunchSize.x + LaunchID.x, cam.frame); - - float r1 = rnd(seed); - float r2 = rnd(seed); - - // Subpixel jitter: send the ray through a different position inside the pixel - // each time, to provide antialiasing. - float2 subpixel_jitter = cam.frame == 0 ? float2(0.5f, 0.5f) : float2(r1, r2); - const float2 pixelCenter = float2(LaunchID.xy) + subpixel_jitter; - const float2 inUV = pixelCenter / float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0, 0, 0, 1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - payload.hitValue = float3(0.0); - float3 hitValues = float3(0); - - const int samples = 4; - - // Trace multiple rays for e.g. transparency - for (int smpl = 0; smpl < samples; smpl++) { - payload.payloadSeed = tea(LaunchID.y * LaunchSize.x + LaunchID.x, cam.frame); - TraceRay(accelStruct, RAY_FLAG_NONE, 0xff, 0, 0, 0, rayDesc, payload); - hitValues += payload.hitValue; - } - - float3 hitVal = hitValues / float(samples); - - if (cam.frame > 0) - { - float a = 1.0f / float(cam.frame + 1); - float3 old_color = image[int2(LaunchID.xy)].xyz; - image[int2(LaunchID.xy)] = float4(lerp(old_color, hitVal, a), 1.0f); - } - else - { - // First frame, replace the value in the buffer - image[int2(LaunchID.xy)] = float4(hitVal, 1.0f); - } -} - -[shader("closesthit")] -void closesthitMain(inout Payload payload, in Attributes attribs) -{ - Triangle tri = unpackTriangle(PrimitiveIndex(), attribs); - payload.hitValue = float3(tri.normal); - - GeometryNode geometryNode = geometryNodes[GeometryIndex()]; - - float3 color = textures[NonUniformResourceIndex(geometryNode.textureIndexBaseColor)].SampleLevel(tri.uv, 0.0).rgb; - if (geometryNode.textureIndexOcclusion > -1) { - float occlusion = textures[NonUniformResourceIndex(geometryNode.textureIndexOcclusion)].SampleLevel(tri.uv, 0.0).r; - color *= occlusion; - } - - payload.hitValue = color; - - // Shadow casting - float tmin = 0.001; - float tmax = 10000.0; - float epsilon = 0.001; - float3 origin = WorldRayOrigin() + WorldRayDirection() * RayTCurrent() + tri.normal * epsilon; - payload.shadowed = true; - float3 lightVector = float3(-5.0, -2.5, -5.0); - // Trace shadow ray and offset indices to match shadow hit/miss shader group indices - // traceRayEXT(topLevelAS, gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT, 0xFF, 0, 0, 1, origin, tmin, lightVector, tmax, 2); - // if (shadowed) { - // hitValue *= 0.7; - // } -} - -[shader("anyhit")] -void anyhitMain(inout Payload payload, in Attributes attribs) -{ - Triangle tri = unpackTriangle(PrimitiveIndex(), attribs); - GeometryNode geometryNode = geometryNodes[GeometryIndex()]; - float4 color = textures[NonUniformResourceIndex(geometryNode.textureIndexBaseColor)].SampleLevel(tri.uv, 0.0); - // If the alpha value of the texture at the current UV coordinates is below a given threshold, we'll ignore this intersection - // That way ray traversal will be stopped and the miss shader will be invoked - if (color.a < 0.9) { - if (rnd(payload.payloadSeed) > color.a) { - IgnoreHit(); - } - } -} - -[shader("miss")] -void missMain(inout Payload payload) -{ - payload.hitValue = float3(1.0); -} \ No newline at end of file diff --git a/shaders/slang/raytracinggltf/shadow.rmiss.spv b/shaders/slang/raytracinggltf/shadow.rmiss.spv deleted file mode 100644 index fdd345de..00000000 Binary files a/shaders/slang/raytracinggltf/shadow.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracinggltf/shadow.slang b/shaders/slang/raytracinggltf/shadow.slang deleted file mode 100644 index 481816ad..00000000 --- a/shaders/slang/raytracinggltf/shadow.slang +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Payload -{ - float3 hitValue; - uint payloadSeed; - bool shadowed; -}; - -[shader("miss")] -void missMain(inout Payload payload) -{ - payload.shadowed = false; -} \ No newline at end of file diff --git a/shaders/slang/raytracingintersection/closesthit.rchit.spv b/shaders/slang/raytracingintersection/closesthit.rchit.spv deleted file mode 100644 index 7cec8e57..00000000 Binary files a/shaders/slang/raytracingintersection/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/slang/raytracingintersection/intersection.rint.spv b/shaders/slang/raytracingintersection/intersection.rint.spv deleted file mode 100644 index d06139f7..00000000 Binary files a/shaders/slang/raytracingintersection/intersection.rint.spv and /dev/null differ diff --git a/shaders/slang/raytracingintersection/miss.rmiss.spv b/shaders/slang/raytracingintersection/miss.rmiss.spv deleted file mode 100644 index 8d1e7b12..00000000 Binary files a/shaders/slang/raytracingintersection/miss.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracingintersection/raygen.rgen.spv b/shaders/slang/raytracingintersection/raygen.rgen.spv deleted file mode 100644 index a49cf0da..00000000 Binary files a/shaders/slang/raytracingintersection/raygen.rgen.spv and /dev/null differ diff --git a/shaders/slang/raytracingintersection/raytracingintersection.slang b/shaders/slang/raytracingintersection/raytracingintersection.slang deleted file mode 100644 index 43251132..00000000 --- a/shaders/slang/raytracingintersection/raytracingintersection.slang +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Payload -{ - float3 hitValue; -} - -RaytracingAccelerationStructure accelStruct; -RWTexture2D image; - -struct UBO -{ - float4x4 viewInverse; - float4x4 projInverse; - float4 lightPos; -}; -ConstantBuffer ubo; - -struct Sphere { - float3 center; - float radius; - float4 color; -}; -StructuredBuffer spheres; - -// Ray-sphere intersection -// By Inigo Quilez, from https://iquilezles.org/articles/spherefunctions/ -float sphIntersect(const Sphere s, float3 ro, float3 rd) -{ - float3 oc = ro - s.center; - float b = dot(oc, rd); - float c = dot(oc, oc) - s.radius * s.radius; - float h = b * b - c; - if (h < 0.0) { - return -1.0; - } - h = sqrt(h); - return -b - h; -} - -[shader("intersection")] -void intersectionMain() { - Sphere sphere = spheres[PrimitiveIndex()]; - float hit = sphIntersect(sphere, WorldRayOrigin(), WorldRayDirection()); - - if (hit > 0) { - ReportHit(hit, 0, 0); - } -} - -[shader("raygeneration")] -void raygenerationMain() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter / float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(ubo.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(ubo.viewInverse, float4(0, 0, 0, 1)).xyz; - rayDesc.Direction = mul(ubo.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - TraceRay(accelStruct, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} - -[shader("closesthit")] -void closesthitMain(inout Payload payload) -{ - Sphere sphere = spheres[PrimitiveIndex()]; - - float3 worldPos = WorldRayOrigin() + WorldRayDirection() * RayTCurrent(); - float3 worldNormal = normalize(worldPos - sphere.center); - - // Basic lighting - float3 lightVector = normalize(ubo.lightPos.xyz); - float dot_product = max(dot(lightVector, worldNormal), 0.2); - payload.hitValue = sphere.color.rgb * dot_product; -} - -[shader("miss")] -void missMain(inout Payload payload) -{ - payload.hitValue = float3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/slang/raytracingpositionfetch/closesthit.rchit.spv b/shaders/slang/raytracingpositionfetch/closesthit.rchit.spv deleted file mode 100644 index 273d9ef9..00000000 Binary files a/shaders/slang/raytracingpositionfetch/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/slang/raytracingpositionfetch/miss.rmiss.spv b/shaders/slang/raytracingpositionfetch/miss.rmiss.spv deleted file mode 100644 index 8d1e7b12..00000000 Binary files a/shaders/slang/raytracingpositionfetch/miss.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracingpositionfetch/raygen.rgen.spv b/shaders/slang/raytracingpositionfetch/raygen.rgen.spv deleted file mode 100644 index a49cf0da..00000000 Binary files a/shaders/slang/raytracingpositionfetch/raygen.rgen.spv and /dev/null differ diff --git a/shaders/slang/raytracingpositionfetch/raytracingpositionfetch.slang b/shaders/slang/raytracingpositionfetch/raytracingpositionfetch.slang deleted file mode 100644 index 96c341e9..00000000 --- a/shaders/slang/raytracingpositionfetch/raytracingpositionfetch.slang +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Attributes -{ - float2 bary; -}; - -struct Payload -{ - [[vk::location(0)]] float3 hitValue; -}; - -RaytracingAccelerationStructure accelStruct; -RWTexture2D image; -struct UBO -{ - float4x4 viewInverse; - float4x4 projInverse; - float4 lightPos; -}; -ConstantBuffer ubo; - -[shader("raygeneration")] -void raygenerationMain() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter / float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(ubo.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(ubo.viewInverse, float4(0, 0, 0, 1)).xyz; - rayDesc.Direction = mul(ubo.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - TraceRay(accelStruct, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} - -[shader("closesthit")] -void closesthitMain(inout Payload payload, in Attributes attribs) -{ - // We need the barycentric coordinates to calculate data for the current position - const float3 barycentricCoords = float3(1.0f - attribs.bary.x - attribs.bary.y, attribs.bary.x, attribs.bary.y); - - // With VK_KHR_ray_tracing_position_fetch we can access the vertices for the hit triangle in the shader - - float3 vertexPos0 = HitTriangleVertexPosition(0); - float3 vertexPos1 = HitTriangleVertexPosition(1); - float3 vertexPos2 = HitTriangleVertexPosition(2); - float3 currentPos = vertexPos0 * barycentricCoords.x + vertexPos1 * barycentricCoords.y + vertexPos2 * barycentricCoords.z; - - // Calcualte the normal from above values - float3 normal = normalize(cross(vertexPos1 - vertexPos0, vertexPos2 - vertexPos0)); - normal = normalize(mul(float4(normal, 1.0), WorldToObject4x3())); - - // Basic lighting - float3 lightDir = normalize(ubo.lightPos.xyz - currentPos); - float diffuse = max(dot(normal, lightDir), 0.0); - - payload.hitValue.rgb = 0.1 + diffuse; -} - -[shader("miss")] -void missMain(inout Payload payload) -{ - payload.hitValue = float3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/slang/raytracingreflections/closesthit.rchit.spv b/shaders/slang/raytracingreflections/closesthit.rchit.spv deleted file mode 100644 index af12d556..00000000 Binary files a/shaders/slang/raytracingreflections/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/slang/raytracingreflections/miss.rmiss.spv b/shaders/slang/raytracingreflections/miss.rmiss.spv deleted file mode 100644 index 714feeb6..00000000 Binary files a/shaders/slang/raytracingreflections/miss.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracingreflections/raygen.rgen.spv b/shaders/slang/raytracingreflections/raygen.rgen.spv deleted file mode 100644 index 7712636d..00000000 Binary files a/shaders/slang/raytracingreflections/raygen.rgen.spv and /dev/null differ diff --git a/shaders/slang/raytracingreflections/raytracingreflections.slang b/shaders/slang/raytracingreflections/raytracingreflections.slang deleted file mode 100644 index 2e9260a9..00000000 --- a/shaders/slang/raytracingreflections/raytracingreflections.slang +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -RaytracingAccelerationStructure accelStruct; -RWTexture2D image; -struct CameraProperties -{ - float4x4 viewInverse; - float4x4 projInverse; - float4 lightPos; - int vertexSize; -}; -ConstantBuffer ubo; -StructuredBuffer vertices; -StructuredBuffer indices; - -// Max. number of recursion is passed via a specialization constant -[SpecializationConstant] const int MAX_RECURSION = 0; - -struct Attributes -{ - float2 bary; -}; - -struct RayPayload -{ - float3 color; - float distance; - float3 normal; - float reflector; -}; - -struct Vertex -{ - float3 pos; - float3 normal; - float2 uv; - float4 color; - float4 _pad0; - float4 _pad1; -}; - -Vertex unpack(uint index) -{ - // Unpack the vertices from the SSBO using the glTF vertex structure - // The multiplier is the size of the vertex divided by four float components (=16 bytes) - const int m = ubo.vertexSize / 16; - - float4 d0 = vertices[m * index + 0]; - float4 d1 = vertices[m * index + 1]; - float4 d2 = vertices[m * index + 2]; - - Vertex v; - v.pos = d0.xyz; - v.normal = float3(d0.w, d1.x, d1.y); - v.color = float4(d2.x, d2.y, d2.z, 1.0); - - return v; -} - -[shader("raygeneration")] -void raygenerationMain() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter / float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(ubo.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(ubo.viewInverse, float4(0, 0, 0, 1)).xyz; - rayDesc.Direction = mul(ubo.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - float3 color = float3(0.0, 0.0, 0.0); - - for (int i = 0; i < MAX_RECURSION; i++) { - RayPayload rayPayload; - TraceRay(accelStruct, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, rayPayload); - float3 hitColor = rayPayload.color; - - if (rayPayload.distance < 0.0f) { - color += hitColor; - break; - } else if (rayPayload.reflector == 1.0f) { - const float3 hitPos = rayDesc.Origin + rayDesc.Direction * rayPayload.distance; - rayDesc.Origin = hitPos + rayPayload.normal * 0.001f; - rayDesc.Direction = reflect(rayDesc.Direction, rayPayload.normal); - } else { - color += hitColor; - break; - } - } - - image[int2(LaunchID.xy)] = float4(color, 0.0); -} - -[shader("closesthit")] -void closesthitMain(inout RayPayload rayPayload, in Attributes attribs) -{ - uint PrimitiveID = PrimitiveIndex(); - int3 index = int3(indices[3 * PrimitiveID], indices[3 * PrimitiveID + 1], indices[3 * PrimitiveID + 2]); - - Vertex v0 = unpack(index.x); - Vertex v1 = unpack(index.y); - Vertex v2 = unpack(index.z); - - // Interpolate normal - const float3 barycentricCoords = float3(1.0f - attribs.bary.x - attribs.bary.y, attribs.bary.x, attribs.bary.y); - float3 normal = normalize(v0.normal * barycentricCoords.x + v1.normal * barycentricCoords.y + v2.normal * barycentricCoords.z); - - // Basic lighting - float3 lightVector = normalize(ubo.lightPos.xyz); - float dot_product = max(dot(lightVector, normal), 0.6); - rayPayload.color.rgb = v0.color.rgb * dot_product; - rayPayload.distance = RayTCurrent(); - rayPayload.normal = normal; - - // Objects with full white vertex color are treated as reflectors - rayPayload.reflector = ((v0.color.r == 1.0f) && (v0.color.g == 1.0f) && (v0.color.b == 1.0f)) ? 1.0f : 0.0f; -} - -[shader("miss")] -void missMain(inout RayPayload rayPayload) -{ - float3 worldRayDirection = WorldRayDirection(); - - // View-independent background gradient to simulate a basic sky background - const float3 gradientStart = float3(0.5, 0.6, 1.0); - const float3 gradientEnd = float3(1.0, 1.0, 1.0); - float3 unitDir = normalize(worldRayDirection); - float t = 0.5 * (unitDir.y + 1.0); - rayPayload.color = (1.0 - t) * gradientStart + t * gradientEnd; - - rayPayload.distance = -1.0f; - rayPayload.normal = float3(0, 0, 0); - rayPayload.reflector = 0.0f; -} \ No newline at end of file diff --git a/shaders/slang/raytracingsbtdata/closesthit.rchit.spv b/shaders/slang/raytracingsbtdata/closesthit.rchit.spv deleted file mode 100644 index 2271821b..00000000 Binary files a/shaders/slang/raytracingsbtdata/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/slang/raytracingsbtdata/miss.rmiss.spv b/shaders/slang/raytracingsbtdata/miss.rmiss.spv deleted file mode 100644 index 4c386b79..00000000 Binary files a/shaders/slang/raytracingsbtdata/miss.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracingsbtdata/raygen.rgen.spv b/shaders/slang/raytracingsbtdata/raygen.rgen.spv deleted file mode 100644 index c215bd7b..00000000 Binary files a/shaders/slang/raytracingsbtdata/raygen.rgen.spv and /dev/null differ diff --git a/shaders/slang/raytracingsbtdata/raytracingsbtdata.slang b/shaders/slang/raytracingsbtdata/raytracingsbtdata.slang deleted file mode 100644 index 5ec0bc13..00000000 --- a/shaders/slang/raytracingsbtdata/raytracingsbtdata.slang +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Attributes -{ - float2 bary; -}; - -struct Payload -{ - float3 hitValue; -}; - -RaytracingAccelerationStructure accelStruct; -RWTexture2D image; -struct CameraProperties -{ - float4x4 viewInverse; - float4x4 projInverse; -}; -ConstantBuffer cam; - -struct SBT { - float r; - float g; - float b; -}; -[[vk::shader_record]] ConstantBuffer sbt; - -[shader("raygeneration")] -void raygenerationMain() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter / float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0, 0, 0, 1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - - // use border to demonstrate raygen record data - if (all(LaunchID.xy > int2(16, 16)) && all(LaunchID.xy < LaunchSize.xy - int2(16, 16))) - { - // Generate a checker board pattern to trace out rays or use hit record data - int2 pos = int2(LaunchID.xy / 16); - if (((pos.x + pos.y % 2) % 2) == 0) { - // This will set hit value to either hit or miss SBT record color - TraceRay(accelStruct, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - } - else { - // Set the hit value to the raygen SBT data - payload.hitValue = float3(sbt.r, sbt.g, sbt.b); - } - } - else { - // Set hit value to black - payload.hitValue = float3(0.0, 0.0, 0.0); - } - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} - -[shader("closesthit")] -void closesthitMain(inout Payload payload, in Attributes attribs) -{ - // Update the hit value to the hit record SBT data associated with this - // geometry ID and ray ID - payload.hitValue = float3(sbt.r, sbt.g, sbt.g); -} - -[shader("miss")] -void missMain(inout Payload payload) -{ - // Update the hit value to the hit record SBT data associated with this - // miss record - payload.hitValue = float3(sbt.r, sbt.g, sbt.g); -} diff --git a/shaders/slang/raytracingshadows/closesthit.rchit.spv b/shaders/slang/raytracingshadows/closesthit.rchit.spv deleted file mode 100644 index d3e84f32..00000000 Binary files a/shaders/slang/raytracingshadows/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/slang/raytracingshadows/miss.rmiss.spv b/shaders/slang/raytracingshadows/miss.rmiss.spv deleted file mode 100644 index 7663e81e..00000000 Binary files a/shaders/slang/raytracingshadows/miss.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracingshadows/payload.slang b/shaders/slang/raytracingshadows/payload.slang deleted file mode 100644 index 5391a15b..00000000 --- a/shaders/slang/raytracingshadows/payload.slang +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -module payload; - -public struct Payload -{ - public float3 hitValue; - public bool shadowed; -}; \ No newline at end of file diff --git a/shaders/slang/raytracingshadows/raygen.rgen.spv b/shaders/slang/raytracingshadows/raygen.rgen.spv deleted file mode 100644 index b0069949..00000000 Binary files a/shaders/slang/raytracingshadows/raygen.rgen.spv and /dev/null differ diff --git a/shaders/slang/raytracingshadows/raytracingshadows.slang b/shaders/slang/raytracingshadows/raytracingshadows.slang deleted file mode 100644 index a7bdb4ae..00000000 --- a/shaders/slang/raytracingshadows/raytracingshadows.slang +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -import payload; - -struct Attributes -{ - float2 bary; -}; - -RaytracingAccelerationStructure accelStruct; -RWTexture2D image; - -struct UBO -{ - float4x4 viewInverse; - float4x4 projInverse; - float4 lightPos; - int vertexSize; -}; -ConstantBuffer ubo; - -StructuredBuffer vertices; -StructuredBuffer indices; - -struct Vertex -{ - float3 pos; - float3 normal; - float2 uv; - float4 color; - float4 _pad0; - float4 _pad1; -}; - -Vertex unpack(uint index) -{ - // Unpack the vertices from the SSBO using the glTF vertex structure - // The multiplier is the size of the vertex divided by four float components (=16 bytes) - const int m = ubo.vertexSize / 16; - - float4 d0 = vertices[m * index + 0]; - float4 d1 = vertices[m * index + 1]; - float4 d2 = vertices[m * index + 2]; - - Vertex v; - v.pos = d0.xyz; - v.normal = float3(d0.w, d1.x, d1.y); - v.color = float4(d2.x, d2.y, d2.z, 1.0); - - return v; -} - -[shader("raygeneration")] -void raygenerationMain() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter / float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(ubo.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(ubo.viewInverse, float4(0, 0, 0, 1)).xyz; - rayDesc.Direction = mul(ubo.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - TraceRay(accelStruct, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload); - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} - -[shader("closesthit")] -void closesthitMain(inout Payload payload, in Attributes attribs) -{ - uint PrimitiveID = PrimitiveIndex(); - int3 index = int3(indices[3 * PrimitiveID], indices[3 * PrimitiveID + 1], indices[3 * PrimitiveID + 2]); - - Vertex v0 = unpack(index.x); - Vertex v1 = unpack(index.y); - Vertex v2 = unpack(index.z); - - // Interpolate normal - const float3 barycentricCoords = float3(1.0f - attribs.bary.x - attribs.bary.y, attribs.bary.x, attribs.bary.y); - float3 normal = normalize(v0.normal * barycentricCoords.x + v1.normal * barycentricCoords.y + v2.normal * barycentricCoords.z); - - // Basic lighting - float3 lightVector = normalize(ubo.lightPos.xyz); - float dot_product = max(dot(lightVector, normal), 0.2); - payload.hitValue = v0.color.rgb * dot_product; - - RayDesc rayDesc; - rayDesc.Origin = WorldRayOrigin() + WorldRayDirection() * RayTCurrent(); - rayDesc.Direction = lightVector; - rayDesc.TMin = 0.001; - rayDesc.TMax = 100.0; - - payload.shadowed = true; - // Offset indices to match shadow hit/miss index - TraceRay(accelStruct, RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_CLOSEST_HIT_SHADER, 0xff, 0, 0, 1, rayDesc, payload); - if (payload.shadowed) { - payload.hitValue *= 0.3; - } -} - -[shader("miss")] -void missMain(inout Payload payload) -{ - payload.hitValue = float3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/slang/raytracingshadows/shadow.rmiss.spv b/shaders/slang/raytracingshadows/shadow.rmiss.spv deleted file mode 100644 index 1f99cf01..00000000 Binary files a/shaders/slang/raytracingshadows/shadow.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracingshadows/shadow.slang b/shaders/slang/raytracingshadows/shadow.slang deleted file mode 100644 index d2149b84..00000000 --- a/shaders/slang/raytracingshadows/shadow.slang +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -import payload; - -[shader("miss")] -void missMain(inout Payload payload) -{ - payload.shadowed = false; -} - diff --git a/shaders/slang/raytracingtextures/anyhit.rahit.spv b/shaders/slang/raytracingtextures/anyhit.rahit.spv deleted file mode 100644 index 021186f1..00000000 Binary files a/shaders/slang/raytracingtextures/anyhit.rahit.spv and /dev/null differ diff --git a/shaders/slang/raytracingtextures/closesthit.rchit.spv b/shaders/slang/raytracingtextures/closesthit.rchit.spv deleted file mode 100644 index fcd3ddbb..00000000 Binary files a/shaders/slang/raytracingtextures/closesthit.rchit.spv and /dev/null differ diff --git a/shaders/slang/raytracingtextures/miss.rmiss.spv b/shaders/slang/raytracingtextures/miss.rmiss.spv deleted file mode 100644 index 8d1e7b12..00000000 Binary files a/shaders/slang/raytracingtextures/miss.rmiss.spv and /dev/null differ diff --git a/shaders/slang/raytracingtextures/raygen.rgen.spv b/shaders/slang/raytracingtextures/raygen.rgen.spv deleted file mode 100644 index 9073f791..00000000 Binary files a/shaders/slang/raytracingtextures/raygen.rgen.spv and /dev/null differ diff --git a/shaders/slang/raytracingtextures/raytracingtextures.slang b/shaders/slang/raytracingtextures/raytracingtextures.slang deleted file mode 100644 index 469a1b5e..00000000 --- a/shaders/slang/raytracingtextures/raytracingtextures.slang +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct Vertex -{ - float3 pos; - float2 uv; -}; - -struct Triangle { - Vertex vertices[3]; - float2 uv; -}; - -struct BufferReferences { - // Pointer to the buffer with the scene's MVP matrix - ConstBufferPointer vertices; - // Pointer to the buffer for the data for each model - ConstBufferPointer indices; -}; -[[vk::push_constant]] BufferReferences bufferReferences; - -struct Payload -{ - float3 hitValue; -}; - -struct UBOCameraProperties { - float4x4 viewInverse; - float4x4 projInverse; -} - -RaytracingAccelerationStructure accelStruct; -RWTexture2D image; -ConstantBuffer cam; -Sampler2D samplerColor; - -struct Attributes -{ - float2 bary; -}; - -Triangle unpackTriangle(uint index, Attributes attribs) { - Triangle tri; - const uint triIndex = index * 3; - const uint vertexSize = 32; - - // Unpack vertices - // Data is packed as float4 so we can map to the glTF vertex structure from the host side - for (uint i = 0; i < 3; i++) { - const uint offset = bufferReferences.indices[triIndex + i] * (vertexSize / 16); - float4 d0 = bufferReferences.vertices[offset + 0]; // pos.xyz, n.x - float4 d1 = bufferReferences.vertices[offset + 1]; // n.yz, uv.xy - tri.vertices[i].pos = d0.xyz; - tri.vertices[i].uv = d1.zw; - } - // Calculate values at barycentric coordinates - float3 barycentricCoords = float3(1.0f - attribs.bary.x - attribs.bary.y, attribs.bary.x, attribs.bary.y); - tri.uv = tri.vertices[0].uv * barycentricCoords.x + tri.vertices[1].uv * barycentricCoords.y + tri.vertices[2].uv * barycentricCoords.z; - return tri; -} - -[shader("raygeneration")] -void raygenerationMain() -{ - uint3 LaunchID = DispatchRaysIndex(); - uint3 LaunchSize = DispatchRaysDimensions(); - - const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5); - const float2 inUV = pixelCenter / float2(LaunchSize.xy); - float2 d = inUV * 2.0 - 1.0; - float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1)); - - RayDesc rayDesc; - rayDesc.Origin = mul(cam.viewInverse, float4(0, 0, 0, 1)).xyz; - rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz; - rayDesc.TMin = 0.001; - rayDesc.TMax = 10000.0; - - Payload payload; - TraceRay(accelStruct, RAY_FLAG_NONE, 0xff, 0, 0, 0, rayDesc, payload); - - image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0); -} - -[shader("closesthit")] -void closesthitMain(inout Payload payload, in Attributes attribs) -{ - Triangle tri = unpackTriangle(PrimitiveIndex(), attribs); - // Fetch the color for this ray hit from the texture at the current uv coordinates - float4 color = samplerColor.SampleLevel(tri.uv, 0.0); - payload.hitValue = color.rgb; -} - -[shader("anyhit")] -void anyhitMain(inout Payload payload, in Attributes attribs) -{ - Triangle tri = unpackTriangle(PrimitiveIndex(), attribs); - float4 color = samplerColor.SampleLevel(tri.uv, 0.0); - // If the alpha value of the texture at the current UV coordinates is below a given threshold, we'll ignore this intersection - // That way ray traversal will be stopped and the miss shader will be invoked - if (color.a < 0.9) { - IgnoreHit(); - } -} - -[shader("miss")] -void missMain(inout Payload payload) -{ - payload.hitValue = float3(0.0, 0.0, 0.2); -} \ No newline at end of file diff --git a/shaders/slang/renderheadless/triangle.frag.spv b/shaders/slang/renderheadless/triangle.frag.spv deleted file mode 100644 index 81761f27..00000000 Binary files a/shaders/slang/renderheadless/triangle.frag.spv and /dev/null differ diff --git a/shaders/slang/renderheadless/triangle.slang b/shaders/slang/renderheadless/triangle.slang deleted file mode 100644 index 11fc0630..00000000 --- a/shaders/slang/renderheadless/triangle.slang +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; -}; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4x4 mvp) -{ - VSOutput output; - output.Color = input.Color; - output.Pos = mul(mvp, float4(input.Pos.xyz, 1.0)); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(input.Color, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/renderheadless/triangle.vert.spv b/shaders/slang/renderheadless/triangle.vert.spv deleted file mode 100644 index 1459c82a..00000000 Binary files a/shaders/slang/renderheadless/triangle.vert.spv and /dev/null differ diff --git a/shaders/slang/screenshot/mesh.frag.spv b/shaders/slang/screenshot/mesh.frag.spv deleted file mode 100644 index 37a0b45e..00000000 Binary files a/shaders/slang/screenshot/mesh.frag.spv and /dev/null differ diff --git a/shaders/slang/screenshot/mesh.slang b/shaders/slang/screenshot/mesh.slang deleted file mode 100644 index abbc7a36..00000000 --- a/shaders/slang/screenshot/mesh.slang +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - - struct VSInput - { - float3 Pos; - float3 Normal; - float3 Color; - }; - - struct VSOutput - { - float4 Pos : SV_POSITION; - float3 Color; - float3 Normal; - float3 ViewVec; - float3 LightVec; - }; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - - output.Normal = mul((float3x3)ubo.model, input.Normal); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - - const float3 lightPos = float3(1.0, -1.0, 1.0); - output.LightVec = lightPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - const float ambient = 0.1; - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0).rrr; - float3 specular = pow(max(dot(R, V), 0.0), 32.0); - return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/screenshot/mesh.vert.spv b/shaders/slang/screenshot/mesh.vert.spv deleted file mode 100644 index 7f5e52b2..00000000 Binary files a/shaders/slang/screenshot/mesh.vert.spv and /dev/null differ diff --git a/shaders/slang/shaderobjects/phong.frag.spv b/shaders/slang/shaderobjects/phong.frag.spv deleted file mode 100644 index 37d29241..00000000 Binary files a/shaders/slang/shaderobjects/phong.frag.spv and /dev/null differ diff --git a/shaders/slang/shaderobjects/phong.slang b/shaders/slang/shaderobjects/phong.slang deleted file mode 100644 index 10e0e0d8..00000000 --- a/shaders/slang/shaderobjects/phong.slang +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; - float3 lPos = mul((float4x3)ubo.model, ubo.lightPos.xyz).xyz; - output.LightVec = lPos.xyz - pos.xyz; - output.ViewVec = -pos.xyz; - - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Desaturate color - float3 color = float3(lerp(input.Color, float3(dot(float3(0.2126, 0.7152, 0.0722), input.Color)), 0.65)); - - // High ambient colors because mesh materials are pretty dark - float3 ambient = color; - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color; - float3 specular = pow(max(dot(R, V), 0.0), 32.0) * float3(0.35); - return float4(ambient + diffuse * 1.75 + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/shaderobjects/phong.vert.spv b/shaders/slang/shaderobjects/phong.vert.spv deleted file mode 100644 index a9e98688..00000000 Binary files a/shaders/slang/shaderobjects/phong.vert.spv and /dev/null differ diff --git a/shaders/slang/shadowmapping/offscreen.frag.spv b/shaders/slang/shadowmapping/offscreen.frag.spv deleted file mode 100644 index bd595cd4..00000000 Binary files a/shaders/slang/shadowmapping/offscreen.frag.spv and /dev/null differ diff --git a/shaders/slang/shadowmapping/offscreen.slang b/shaders/slang/shadowmapping/offscreen.slang deleted file mode 100644 index decb80c3..00000000 --- a/shaders/slang/shadowmapping/offscreen.slang +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct UBO -{ - float4x4 depthMVP; -}; -ConstantBuffer ubo; - -[shader("vertex")] -float4 vertexMain(float3 Pos) : SV_POSITION -{ - return mul(ubo.depthMVP, float4(Pos, 1.0)); -} - -[shader("fragment")] -float4 fragmentMain() -{ - return float4(1.0, 0.0, 0.0, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/shadowmapping/offscreen.vert.spv b/shaders/slang/shadowmapping/offscreen.vert.spv deleted file mode 100644 index a9c7c1db..00000000 Binary files a/shaders/slang/shadowmapping/offscreen.vert.spv and /dev/null differ diff --git a/shaders/slang/shadowmapping/quad.frag.spv b/shaders/slang/shadowmapping/quad.frag.spv deleted file mode 100644 index 893e62cd..00000000 Binary files a/shaders/slang/shadowmapping/quad.frag.spv and /dev/null differ diff --git a/shaders/slang/shadowmapping/quad.slang b/shaders/slang/shadowmapping/quad.slang deleted file mode 100644 index c6237b1d..00000000 --- a/shaders/slang/shadowmapping/quad.slang +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4x4 lightSpace; - float4 lightPos; - float zNear; - float zFar; -}; -ConstantBuffer ubo; -Sampler2D samplerColor; - -float LinearizeDepth(float depth) -{ - float n = ubo.zNear; - float f = ubo.zFar; - float z = depth; - return (2.0 * n) / (f + n - z * (f - n)); -} - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float depth = samplerColor.Sample(input.UV).r; - return float4((1.0 - LinearizeDepth(depth)).xxx, 1.0); -} diff --git a/shaders/slang/shadowmapping/quad.vert.spv b/shaders/slang/shadowmapping/quad.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/shadowmapping/quad.vert.spv and /dev/null differ diff --git a/shaders/slang/shadowmapping/scene.frag.spv b/shaders/slang/shadowmapping/scene.frag.spv deleted file mode 100644 index 4f8867db..00000000 Binary files a/shaders/slang/shadowmapping/scene.frag.spv and /dev/null differ diff --git a/shaders/slang/shadowmapping/scene.slang b/shaders/slang/shadowmapping/scene.slang deleted file mode 100644 index 2f9395a6..00000000 --- a/shaders/slang/shadowmapping/scene.slang +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; - float4 ShadowCoord; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4x4 lightSpace; - float4 lightPos; - float zNear; - float zFar; -}; -ConstantBuffer ubo; -Sampler2D shadowMapSampler; - -[SpecializationConstant] const int enablePCF = 0; - -#define ambient 0.1 - -float textureProj(float4 shadowCoord, float2 off) -{ - float shadow = 1.0; - if ( shadowCoord.z > -1.0 && shadowCoord.z < 1.0 ) - { - float dist = shadowMapSampler.Sample(shadowCoord.xy + off).r; - if ( shadowCoord.w > 0.0 && dist < shadowCoord.z ) - { - shadow = ambient; - } - } - return shadow; -} - -float filterPCF(float4 sc) -{ - int2 texDim; - shadowMapSampler.GetDimensions(texDim.x, texDim.y); - float scale = 1.5; - float dx = scale * 1.0 / float(texDim.x); - float dy = scale * 1.0 / float(texDim.y); - - float shadowFactor = 0.0; - int count = 0; - int range = 1; - - for (int x = -range; x <= range; x++) - { - for (int y = -range; y <= range; y++) - { - shadowFactor += textureProj(sc, float2(dx*x, dy*y)); - count++; - } - - } - return shadowFactor / count; -} - -static const float4x4 biasMat = float4x4( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0); - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output = (VSOutput)0; - output.Color = input.Color; - output.Normal = input.Normal; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.LightVec = normalize(ubo.lightPos.xyz - input.Pos); - output.ViewVec = -pos.xyz; - - output.ShadowCoord = mul(biasMat, mul(ubo.lightSpace, mul(ubo.model, float4(input.Pos, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float shadow = (enablePCF == 1) ? filterPCF(input.ShadowCoord / input.ShadowCoord.w) : textureProj(input.ShadowCoord / input.ShadowCoord.w, float2(0.0, 0.0)); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = normalize(-reflect(L, N)); - float3 diffuse = max(dot(N, L), ambient) * input.Color; - - return float4(diffuse * shadow, 1.0); -} diff --git a/shaders/slang/shadowmapping/scene.vert.spv b/shaders/slang/shadowmapping/scene.vert.spv deleted file mode 100644 index c1e316eb..00000000 Binary files a/shaders/slang/shadowmapping/scene.vert.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingcascade/debugshadowmap.frag.spv b/shaders/slang/shadowmappingcascade/debugshadowmap.frag.spv deleted file mode 100644 index a5facaad..00000000 Binary files a/shaders/slang/shadowmappingcascade/debugshadowmap.frag.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingcascade/debugshadowmap.slang b/shaders/slang/shadowmappingcascade/debugshadowmap.slang deleted file mode 100644 index 925b7d51..00000000 --- a/shaders/slang/shadowmappingcascade/debugshadowmap.slang +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -[[vk::binding(1,0)]] Sampler2DArray shadowMapSampler; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input, uniform float4 meshPosition, uniform uint cascadeIndex) -{ - float depth = shadowMapSampler.Sample(float3(input.UV, float(cascadeIndex))).r; - return float4(depth.xxx, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/shadowmappingcascade/debugshadowmap.vert.spv b/shaders/slang/shadowmappingcascade/debugshadowmap.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/shadowmappingcascade/debugshadowmap.vert.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingcascade/depthpass.frag.spv b/shaders/slang/shadowmappingcascade/depthpass.frag.spv deleted file mode 100644 index ccca898c..00000000 Binary files a/shaders/slang/shadowmappingcascade/depthpass.frag.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingcascade/depthpass.slang b/shaders/slang/shadowmappingcascade/depthpass.slang deleted file mode 100644 index 287fe6c8..00000000 --- a/shaders/slang/shadowmappingcascade/depthpass.slang +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -// todo: pass via specialization constant -#define SHADOW_MAP_CASCADE_COUNT 4 - -struct UBO { - float4x4 cascadeViewProjMat[SHADOW_MAP_CASCADE_COUNT]; -}; -[[vk::binding(3, 0)]] ConstantBuffer ubo; - -[[vk::binding(0, 1)]] Sampler2D colorMapSampler : register(s0, space1); - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4 meshPosition, uniform uint cascadeIndex) -{ - VSOutput output; - output.UV = input.UV; - float3 pos = input.Pos + meshPosition.xyz; - output.Pos = mul(ubo.cascadeViewProjMat[cascadeIndex], float4(pos, 1.0)); - return output; -} - -[shader("fragment")] -void fragmentMain(VSOutput input) -{ - float alpha = colorMapSampler.Sample(input.UV).a; - if (alpha < 0.5) { - clip(-1); - } -} \ No newline at end of file diff --git a/shaders/slang/shadowmappingcascade/depthpass.vert.spv b/shaders/slang/shadowmappingcascade/depthpass.vert.spv deleted file mode 100644 index 020cdb0d..00000000 Binary files a/shaders/slang/shadowmappingcascade/depthpass.vert.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingcascade/scene.frag.spv b/shaders/slang/shadowmappingcascade/scene.frag.spv deleted file mode 100644 index 3bf83962..00000000 Binary files a/shaders/slang/shadowmappingcascade/scene.frag.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingcascade/scene.slang b/shaders/slang/shadowmappingcascade/scene.slang deleted file mode 100644 index 8e4bdd56..00000000 --- a/shaders/slang/shadowmappingcascade/scene.slang +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -#define SHADOW_MAP_CASCADE_COUNT 4 - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 ViewPos; - float3 WorldPos; - float2 UV; -}; - -[SpecializationConstant] const int enablePCF = 0; - -#define ambient 0.3 - -struct UBOScene { - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer uboScene; - -[[vk::binding(1, 0)]] Sampler2DArray shadowMapSampler; - -struct UBOCascades { - float4 cascadeSplits; - float4x4 inverseViewMat; - float3 lightDir; - float _pad; - int colorCascades; -}; -[[vk::binding(2, 0)]] ConstantBuffer uboCascades; - -struct CVPM { - float4x4 matrices[SHADOW_MAP_CASCADE_COUNT]; -}; -[[vk::binding(3, 0)]] ConstantBuffer cascadeViewProjMatrices; - -[[vk::binding(0, 1)]] Sampler2D colorMapSampler; - -static const float4x4 biasMat = float4x4( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 -); - -float textureProj(float4 shadowCoord, float2 offset, uint cascadeIndex) -{ - float shadow = 1.0; - float bias = 0.005; - - if (shadowCoord.z > -1.0 && shadowCoord.z < 1.0) { - float dist = shadowMapSampler.Sample(float3(shadowCoord.xy + offset, cascadeIndex)).r; - if (shadowCoord.w > 0 && dist < shadowCoord.z - bias) { - shadow = ambient; - } - } - return shadow; -} - -float filterPCF(float4 sc, uint cascadeIndex) -{ - int3 texDim; - shadowMapSampler.GetDimensions(texDim.x, texDim.y, texDim.z); - float scale = 0.75; - float dx = scale * 1.0 / float(texDim.x); - float dy = scale * 1.0 / float(texDim.y); - - float shadowFactor = 0.0; - int count = 0; - int range = 1; - - for (int x = -range; x <= range; x++) { - for (int y = -range; y <= range; y++) { - shadowFactor += textureProj(sc, float2(dx*x, dy*y), cascadeIndex); - count++; - } - } - return shadowFactor / count; -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4 meshPosition) -{ - VSOutput output; - output.Color = input.Color; - output.Normal = input.Normal; - output.UV = input.UV; - float3 pos = input.Pos + meshPosition.xyz; - output.WorldPos = pos; - output.ViewPos = mul(uboScene.view, float4(pos.xyz, 1.0)).xyz; - output.Pos = mul(uboScene.projection, mul(uboScene.view, mul(uboScene.model, float4(pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 outFragColor; - float4 color = colorMapSampler.Sample(input.UV); - if (color.a < 0.5) { - clip(-1); - } - - // Get cascade index for the current fragment's view position - uint cascadeIndex = 0; - for (uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i) { - if (input.ViewPos.z < uboCascades.cascadeSplits[i]) { - cascadeIndex = i + 1; - } - } - - // Depth compare for shadowing - float4 shadowCoord = mul(biasMat, mul(cascadeViewProjMatrices.matrices[cascadeIndex], float4(input.WorldPos, 1.0))); - - float shadow = 0; - if (enablePCF == 1) { - shadow = filterPCF(shadowCoord / shadowCoord.w, cascadeIndex); - } else { - shadow = textureProj(shadowCoord / shadowCoord.w, float2(0.0, 0.0), cascadeIndex); - } - - // Directional light - float3 N = normalize(input.Normal); - float3 L = normalize(-uboCascades.lightDir); - float3 H = normalize(L + input.ViewPos); - float diffuse = max(dot(N, L), ambient); - float3 lightColor = float3(1.0, 1.0, 1.0); - outFragColor.rgb = max(lightColor * (diffuse * color.rgb), float3(0.0, 0.0, 0.0)); - outFragColor.rgb *= shadow; - outFragColor.a = color.a; - - // Color cascades (if enabled) - if (uboCascades.colorCascades == 1) { - switch(cascadeIndex) { - case 0 : - outFragColor.rgb *= float3(1.0f, 0.25f, 0.25f); - break; - case 1 : - outFragColor.rgb *= float3(0.25f, 1.0f, 0.25f); - break; - case 2 : - outFragColor.rgb *= float3(0.25f, 0.25f, 1.0f); - break; - case 3 : - outFragColor.rgb *= float3(1.0f, 1.0f, 0.25f); - break; - } - } - - return outFragColor; -} diff --git a/shaders/slang/shadowmappingcascade/scene.vert.spv b/shaders/slang/shadowmappingcascade/scene.vert.spv deleted file mode 100644 index 385bd66a..00000000 Binary files a/shaders/slang/shadowmappingcascade/scene.vert.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingomni/cubemapdisplay.frag.spv b/shaders/slang/shadowmappingomni/cubemapdisplay.frag.spv deleted file mode 100644 index 7942cd24..00000000 Binary files a/shaders/slang/shadowmappingomni/cubemapdisplay.frag.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingomni/cubemapdisplay.slang b/shaders/slang/shadowmappingomni/cubemapdisplay.slang deleted file mode 100644 index bb4b4a49..00000000 --- a/shaders/slang/shadowmappingomni/cubemapdisplay.slang +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; -}; -ConstantBuffer ubo; - -SamplerCube shadowCubeMapSampler; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV.xy * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 outFragColor = float4(0, 0, 0, 0); - outFragColor.rgb = float3(0.05, 0.05, 0.05); - - float3 samplePos = float3(0, 0, 0); - - // Crude statement to visualize different cube map faces based on UV coordinates - int x = int(floor(input.UV.x / 0.25f)); - int y = int(floor(input.UV.y / (1.0 / 3.0))); - if (y == 1) { - float2 uv = float2(input.UV.x * 4.0f, (input.UV.y - 1.0/3.0) * 3.0); - uv = 2.0 * float2(uv.x - float(x) * 1.0, uv.y) - 1.0; - switch (x) { - case 0: // NEGATIVE_X - samplePos = float3(-1.0f, uv.y, uv.x); - break; - case 1: // POSITIVE_Z - samplePos = float3(uv.x, uv.y, 1.0f); - break; - case 2: // POSITIVE_X - samplePos = float3(1.0, uv.y, -uv.x); - break; - case 3: // NEGATIVE_Z - samplePos = float3(-uv.x, uv.y, -1.0f); - break; - } - } else { - if (x == 1) { - float2 uv = float2((input.UV.x - 0.25) * 4.0, (input.UV.y - float(y) / 3.0) * 3.0); - uv = 2.0 * uv - 1.0; - switch (y) { - case 0: // NEGATIVE_Y - samplePos = float3(uv.x, -1.0f, uv.y); - break; - case 2: // POSITIVE_Y - samplePos = float3(uv.x, 1.0f, -uv.y); - break; - } - } - } - - if ((samplePos.x != 0.0f) && (samplePos.y != 0.0f)) { - float dist = length(shadowCubeMapSampler.Sample(samplePos).xyz) * 0.005; - outFragColor = float4(dist.xxx, 1.0); - } - return outFragColor; -} \ No newline at end of file diff --git a/shaders/slang/shadowmappingomni/cubemapdisplay.vert.spv b/shaders/slang/shadowmappingomni/cubemapdisplay.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/shadowmappingomni/cubemapdisplay.vert.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingomni/offscreen.frag.spv b/shaders/slang/shadowmappingomni/offscreen.frag.spv deleted file mode 100644 index 01d9e3fc..00000000 Binary files a/shaders/slang/shadowmappingomni/offscreen.frag.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingomni/offscreen.slang b/shaders/slang/shadowmappingomni/offscreen.slang deleted file mode 100644 index 243447ea..00000000 --- a/shaders/slang/shadowmappingomni/offscreen.slang +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float4 WorldPos; - float3 LightPos; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4x4 view) -{ - VSOutput output; - output.Pos = mul(ubo.projection, mul(view, mul(ubo.model, float4(input.Pos, 1.0)))); - - output.WorldPos = float4(input.Pos, 1.0); - output.LightPos = ubo.lightPos.xyz; - return output; -} - -[shader("fragment")] -float fragmentMain(VSOutput input) -{ - // Store distance to light as 32 bit float value - float3 lightVec = input.WorldPos.xyz - input.LightPos; - return length(lightVec); -} \ No newline at end of file diff --git a/shaders/slang/shadowmappingomni/offscreen.vert.spv b/shaders/slang/shadowmappingomni/offscreen.vert.spv deleted file mode 100644 index 509363a2..00000000 Binary files a/shaders/slang/shadowmappingomni/offscreen.vert.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingomni/scene.frag.spv b/shaders/slang/shadowmappingomni/scene.frag.spv deleted file mode 100644 index d03d764c..00000000 Binary files a/shaders/slang/shadowmappingomni/scene.frag.spv and /dev/null differ diff --git a/shaders/slang/shadowmappingomni/scene.slang b/shaders/slang/shadowmappingomni/scene.slang deleted file mode 100644 index b5296ed7..00000000 --- a/shaders/slang/shadowmappingomni/scene.slang +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 EyePos; - float3 LightVec; - float3 WorldPos; - float3 LightPos; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -SamplerCube shadowCubeMapSampler; - -#define EPSILON 0.15 -#define SHADOW_OPACITY 0.5 - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Normal = input.Normal; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - output.EyePos = mul(ubo.model, float4(input.Pos, 1.0f)).xyz; - output.LightVec = normalize(ubo.lightPos.xyz - input.Pos.xyz); - output.WorldPos = input.Pos; - - output.LightPos = ubo.lightPos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Lighting - float3 N = normalize(input.Normal); - float3 L = normalize(float3(1.0, 1.0, 1.0)); - - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - - float4 IAmbient = float4(float3(0.05, 0.05, 0.05), 1.0); - float4 IDiffuse = float4(1.0, 1.0, 1.0, 1.0) * max(dot(input.Normal, input.LightVec), 0.0); - - float4 outFragColor = float4(IAmbient + IDiffuse * float4(input.Color, 1.0)); - - // Shadow - float3 lightVec = input.WorldPos - input.LightPos; - float sampledDist = shadowCubeMapSampler.Sample(lightVec).r; - float dist = length(lightVec); - - // Check if fragment is in shadow - float shadow = (dist <= sampledDist + EPSILON) ? 1.0 : SHADOW_OPACITY; - - outFragColor.rgb *= shadow; - return outFragColor; -} \ No newline at end of file diff --git a/shaders/slang/shadowmappingomni/scene.vert.spv b/shaders/slang/shadowmappingomni/scene.vert.spv deleted file mode 100644 index 0e8ba849..00000000 Binary files a/shaders/slang/shadowmappingomni/scene.vert.spv and /dev/null differ diff --git a/shaders/slang/specializationconstants/uber.frag.spv b/shaders/slang/specializationconstants/uber.frag.spv deleted file mode 100644 index b8c081d7..00000000 Binary files a/shaders/slang/specializationconstants/uber.frag.spv and /dev/null differ diff --git a/shaders/slang/specializationconstants/uber.slang b/shaders/slang/specializationconstants/uber.slang deleted file mode 100644 index 14fc8af5..00000000 --- a/shaders/slang/specializationconstants/uber.slang +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -Sampler2D samplerColormap; -Sampler2D samplerDiscard; - -// We use this constant to control the flow of the shader depending on the -// lighting model selected at pipeline creation time -[[SpecializationConstant]] const int LIGHTING_MODEL = 0; -// Parameter for the toon shading part of the shader -[[SpecializationConstant]] const int PARAM_TOON_DESATURATION = 0; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - switch (LIGHTING_MODEL) { - case 0: // Phong - { - float3 ambient = input.Color * float3(0.25, 0.25, 0.25); - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * input.Color; - float3 specular = pow(max(dot(R, V), 0.0), 32.0) * float3(0.75, 0.75, 0.75); - return float4(ambient + diffuse * 1.75 + specular, 1.0); - } - case 1: // Toon - { - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float intensity = dot(N,L); - float3 color; - if (intensity > 0.98) - color = input.Color * 1.5; - else if (intensity > 0.9) - color = input.Color * 1.0; - else if (intensity > 0.5) - color = input.Color * 0.6; - else if (intensity > 0.25) - color = input.Color * 0.4; - else - color = input.Color * 0.2; - // Desaturate a bit - color = float3(lerp(color, dot(float3(0.2126,0.7152,0.0722), color).xxx, asfloat(PARAM_TOON_DESATURATION))); - return float4(color, 1); - } - case 2: // Textured - { - float4 color = samplerColormap.Sample(input.UV).rrra; - float3 ambient = color.rgb * float3(0.25, 0.25, 0.25) * input.Color; - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * color.rgb; - float specular = pow(max(dot(R, V), 0.0), 32.0) * color.a; - return float4(ambient + diffuse + specular.xxx, 1.0); - } - } - - return float4(0, 0, 0, 0); -} \ No newline at end of file diff --git a/shaders/slang/specializationconstants/uber.vert.spv b/shaders/slang/specializationconstants/uber.vert.spv deleted file mode 100644 index 7f77237d..00000000 Binary files a/shaders/slang/specializationconstants/uber.vert.spv and /dev/null differ diff --git a/shaders/slang/sphericalenvmapping/sem.frag.spv b/shaders/slang/sphericalenvmapping/sem.frag.spv deleted file mode 100644 index a210331f..00000000 Binary files a/shaders/slang/sphericalenvmapping/sem.frag.spv and /dev/null differ diff --git a/shaders/slang/sphericalenvmapping/sem.slang b/shaders/slang/sphericalenvmapping/sem.slang deleted file mode 100644 index 28f75f31..00000000 --- a/shaders/slang/sphericalenvmapping/sem.slang +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; - float3 EyePos; - float3 Normal; - int TexIndex; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 normal; - float4x4 view; - int texIndex; -}; -ConstantBuffer ubo; - -Sampler2DArray matCapSampler; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - float4x4 modelView = mul(ubo.view, ubo.model); - output.EyePos = normalize(mul(modelView, input.Pos).xyz); - output.TexIndex = ubo.texIndex; - output.Normal = normalize(mul((float3x3)ubo.normal, input.Normal)); - float3 r = reflect(output.EyePos, output.Normal); - float m = 2.0 * sqrt(pow(r.x, 2.0) + pow(r.y, 2.0) + pow(r.z + 1.0, 2.0)); - output.Pos = mul(ubo.projection, mul(modelView, input.Pos)); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 r = reflect( input.EyePos, input.Normal ); - float3 r2 = float3( r.x, r.y, r.z + 1.0 ); - float m = 2.0 * length( r2 ); - float2 vN = r.xy / m + .5; - return float4(matCapSampler.Sample(float3(vN, input.TexIndex)).rgb * (clamp(input.Color.r * 2, 0.0, 1.0)), 1.0); -} diff --git a/shaders/slang/sphericalenvmapping/sem.vert.spv b/shaders/slang/sphericalenvmapping/sem.vert.spv deleted file mode 100644 index e1356455..00000000 Binary files a/shaders/slang/sphericalenvmapping/sem.vert.spv and /dev/null differ diff --git a/shaders/slang/ssao/blur.frag.spv b/shaders/slang/ssao/blur.frag.spv deleted file mode 100644 index 7a867756..00000000 Binary files a/shaders/slang/ssao/blur.frag.spv and /dev/null differ diff --git a/shaders/slang/ssao/blur.slang b/shaders/slang/ssao/blur.slang deleted file mode 100644 index b35d087d..00000000 --- a/shaders/slang/ssao/blur.slang +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -import types; - -Sampler2D samplerSSAO; - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - const int blurRange = 2; - int n = 0; - int2 texDim; - samplerSSAO.GetDimensions(texDim.x, texDim.y); - float2 texelSize = 1.0 / (float2)texDim; - float result = 0.0; - for (int x = -blurRange; x <= blurRange; x++) - { - for (int y = -blurRange; y <= blurRange; y++) - { - float2 offset = float2(float(x), float(y)) * texelSize; - result += samplerSSAO.Sample(input.UV + offset).r; - n++; - } - } - return result / (float(n)); -} \ No newline at end of file diff --git a/shaders/slang/ssao/composition.frag.spv b/shaders/slang/ssao/composition.frag.spv deleted file mode 100644 index 7f5330c7..00000000 Binary files a/shaders/slang/ssao/composition.frag.spv and /dev/null differ diff --git a/shaders/slang/ssao/composition.slang b/shaders/slang/ssao/composition.slang deleted file mode 100644 index 04991a03..00000000 --- a/shaders/slang/ssao/composition.slang +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -import types; - -Sampler2D samplerposition; -Sampler2D samplerNormal; -Sampler2D samplerAlbedo; -Sampler2D samplerSSAO; -Sampler2D samplerSSAOBlur; - -struct UBO -{ - float4x4 _dummy; - int ssao; - int ssaoOnly; - int ssaoBlur; -}; -ConstantBuffer uboParams; - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 fragPos = samplerposition.Sample(input.UV).rgb; - float3 normal = normalize(samplerNormal.Sample(input.UV).rgb * 2.0 - 1.0); - float4 albedo = samplerAlbedo.Sample(input.UV); - - float ssao = (uboParams.ssaoBlur == 1) ? samplerSSAOBlur.Sample(input.UV).r : samplerSSAO.Sample(input.UV).r; - - float3 lightPos = float3(0.0, 0.0, 0.0); - float3 L = normalize(lightPos - fragPos); - float NdotL = max(0.5, dot(normal, L)); - - float4 outFragColor; - if (uboParams.ssaoOnly == 1) - { - outFragColor.rgb = ssao.rrr; - } - else - { - float3 baseColor = albedo.rgb * NdotL; - - if (uboParams.ssao == 1) - { - outFragColor.rgb = ssao.rrr; - - if (uboParams.ssaoOnly != 1) - outFragColor.rgb *= baseColor; - } - else - { - outFragColor.rgb = baseColor; - } - } - return outFragColor; -} \ No newline at end of file diff --git a/shaders/slang/ssao/fullscreen.slang b/shaders/slang/ssao/fullscreen.slang deleted file mode 100644 index d734ebc5..00000000 --- a/shaders/slang/ssao/fullscreen.slang +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -import types; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex : SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} diff --git a/shaders/slang/ssao/fullscreen.vert.spv b/shaders/slang/ssao/fullscreen.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/ssao/fullscreen.vert.spv and /dev/null differ diff --git a/shaders/slang/ssao/gbuffer.frag.spv b/shaders/slang/ssao/gbuffer.frag.spv deleted file mode 100644 index 8821efa1..00000000 Binary files a/shaders/slang/ssao/gbuffer.frag.spv and /dev/null differ diff --git a/shaders/slang/ssao/gbuffer.slang b/shaders/slang/ssao/gbuffer.slang deleted file mode 100644 index 73e4d9dd..00000000 --- a/shaders/slang/ssao/gbuffer.slang +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float2 UV; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; - float3 Color; - float3 WorldPos; -}; - -struct FSOutput -{ - float4 Position : SV_TARGET0; - float4 Normal : SV_TARGET1; - float4 Albedo : SV_TARGET2; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; - float nearPlane; - float farPlane; -}; -ConstantBuffer ubo; - -[[vk::binding(0, 1)]] Texture2D textureColorMap; -[[vk::binding(0, 1)]] SamplerState samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos))); - output.UV = input.UV; - // Vertex position in view space - output.WorldPos = mul(ubo.view, mul(ubo.model, input.Pos)).xyz; - // Normal in view space - float3x3 normalMatrix = (float3x3)mul(ubo.view, ubo.model); - output.Normal = mul(normalMatrix, input.Normal); - output.Color = input.Color; - return output; -} - -float linearDepth(float depth) -{ - float z = depth * 2.0f - 1.0f; - return (2.0f * ubo.nearPlane * ubo.farPlane) / (ubo.farPlane + ubo.nearPlane - z * (ubo.farPlane - ubo.nearPlane)); -} - -[shader("fragment")] -FSOutput fragmentMain(VSOutput input) -{ - FSOutput output; - output.Position = float4(input.WorldPos, linearDepth(input.Pos.z)); - output.Normal = float4(normalize(input.Normal) * 0.5 + 0.5, 1.0); - output.Albedo = textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0); - return output; -} \ No newline at end of file diff --git a/shaders/slang/ssao/gbuffer.vert.spv b/shaders/slang/ssao/gbuffer.vert.spv deleted file mode 100644 index a4467b5c..00000000 Binary files a/shaders/slang/ssao/gbuffer.vert.spv and /dev/null differ diff --git a/shaders/slang/ssao/ssao.frag.spv b/shaders/slang/ssao/ssao.frag.spv deleted file mode 100644 index d5881aed..00000000 Binary files a/shaders/slang/ssao/ssao.frag.spv and /dev/null differ diff --git a/shaders/slang/ssao/ssao.slang b/shaders/slang/ssao/ssao.slang deleted file mode 100644 index 624a5f78..00000000 --- a/shaders/slang/ssao/ssao.slang +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -import types; - -Sampler2D samplerPositionDepth; -Sampler2D samplerNormal; -Sampler2D ssaoNoiseSampler; - -struct UBOSSAOKernel -{ - float4 samples[64]; -}; -ConstantBuffer uboSSAOKernel; - -struct UBO -{ - float4x4 projection; -}; -ConstantBuffer ubo; - -[[SpecializationConstant]] const int SSAO_KERNEL_SIZE = 64; -[[SpecializationConstant]] const float SSAO_RADIUS = 0.5; - -[shader("fragment")] -float fragmentMain(VSOutput input) -{ - // Get G-Buffer values - float3 fragPos = samplerPositionDepth.Sample(input.UV).rgb; - float3 normal = normalize(samplerNormal.Sample(input.UV).rgb * 2.0 - 1.0); - - // Get a random vector using a noise lookup - int2 texDim; - samplerPositionDepth.GetDimensions(texDim.x, texDim.y); - int2 noiseDim; - ssaoNoiseSampler.GetDimensions(noiseDim.x, noiseDim.y); - const float2 noiseUV = float2(float(texDim.x) / float(noiseDim.x), float(texDim.y) / (noiseDim.y)) * input.UV; - float3 randomVec = ssaoNoiseSampler.Sample(noiseUV).xyz * 2.0 - 1.0; - - // Create TBN matrix - float3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); - float3 bitangent = cross(tangent, normal); - float3x3 TBN = transpose(float3x3(tangent, bitangent, normal)); - - // Calculate occlusion value - float occlusion = 0.0f; - for(int i = 0; i < SSAO_KERNEL_SIZE; i++) - { - float3 samplePos = mul(TBN, uboSSAOKernel.samples[i].xyz); - samplePos = fragPos + samplePos * SSAO_RADIUS; - - // project - float4 offset = float4(samplePos, 1.0f); - offset = mul(ubo.projection, offset); - offset.xyz /= offset.w; - offset.xyz = offset.xyz * 0.5f + 0.5f; - - float sampleDepth = -samplerPositionDepth.Sample(offset.xy).w; - - float rangeCheck = smoothstep(0.0f, 1.0f, SSAO_RADIUS / abs(fragPos.z - sampleDepth)); - occlusion += (sampleDepth >= samplePos.z ? 1.0f : 0.0f) * rangeCheck; - } - occlusion = 1.0 - (occlusion / float(SSAO_KERNEL_SIZE)); - - return occlusion; -} - diff --git a/shaders/slang/ssao/types.slang b/shaders/slang/ssao/types.slang deleted file mode 100644 index 52f46ab3..00000000 --- a/shaders/slang/ssao/types.slang +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -module types; - -public struct VSOutput -{ - public float4 Pos : SV_POSITION; - public float2 UV; -}; diff --git a/shaders/slang/stencilbuffer/outline.frag.spv b/shaders/slang/stencilbuffer/outline.frag.spv deleted file mode 100644 index 5cbccf9c..00000000 Binary files a/shaders/slang/stencilbuffer/outline.frag.spv and /dev/null differ diff --git a/shaders/slang/stencilbuffer/outline.slang b/shaders/slang/stencilbuffer/outline.slang deleted file mode 100644 index 332f220d..00000000 --- a/shaders/slang/stencilbuffer/outline.slang +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; -} - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; - float outlineWidth; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - // Extrude along normal - VSOutput output; - float4 pos = float4(input.Pos.xyz + input.Normal * ubo.outlineWidth, input.Pos.w); - output.Pos = mul(ubo.projection, mul(ubo.model, pos)); - return output; -} - -[shader("fragment")] -float4 fragmentMain() -{ - return float4(1.0, 1.0, 1.0, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/stencilbuffer/outline.vert.spv b/shaders/slang/stencilbuffer/outline.vert.spv deleted file mode 100644 index a34b5835..00000000 Binary files a/shaders/slang/stencilbuffer/outline.vert.spv and /dev/null differ diff --git a/shaders/slang/stencilbuffer/toon.frag.spv b/shaders/slang/stencilbuffer/toon.frag.spv deleted file mode 100644 index 355dcc22..00000000 Binary files a/shaders/slang/stencilbuffer/toon.frag.spv and /dev/null differ diff --git a/shaders/slang/stencilbuffer/toon.slang b/shaders/slang/stencilbuffer/toon.slang deleted file mode 100644 index b7bf1314..00000000 --- a/shaders/slang/stencilbuffer/toon.slang +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = float3(1.0, 0.0, 0.0); - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 color; - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float intensity = dot(N,L); - if (intensity > 0.98) - color = input.Color * 1.5; - else if (intensity > 0.9) - color = input.Color * 1.0; - else if (intensity > 0.5) - color = input.Color * 0.6; - else if (intensity > 0.25) - color = input.Color * 0.4; - else - color = input.Color * 0.2; - // Desaturate a bit - color = lerp(color, dot(float3(0.2126,0.7152,0.0722), color).xxx, 0.1); - return float4(color, 1); -} \ No newline at end of file diff --git a/shaders/slang/stencilbuffer/toon.vert.spv b/shaders/slang/stencilbuffer/toon.vert.spv deleted file mode 100644 index aa676e9b..00000000 Binary files a/shaders/slang/stencilbuffer/toon.vert.spv and /dev/null differ diff --git a/shaders/slang/subpasses/composition.frag.spv b/shaders/slang/subpasses/composition.frag.spv deleted file mode 100644 index e5068101..00000000 Binary files a/shaders/slang/subpasses/composition.frag.spv and /dev/null differ diff --git a/shaders/slang/subpasses/composition.slang b/shaders/slang/subpasses/composition.slang deleted file mode 100644 index 728f1452..00000000 --- a/shaders/slang/subpasses/composition.slang +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -[[vk::input_attachment_index(0)]] SubpassInput inputPosition; -[[vk::input_attachment_index(1)]] SubpassInput inputNormal; -[[vk::input_attachment_index(2)]] SubpassInput inputAlbedo; - -struct Light { - float4 position; - float3 color; - float radius; -}; -RWStructuredBuffer lights; - -[shader("vertex")] -VSOutput vertexMain(uint VertexIndex: SV_VertexID) -{ - VSOutput output; - output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); - output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); - return output; -} - -[shader("fragment")] -float4 fragmentMain() -{ - // Read G-Buffer values from previous sub pass - float3 fragPos = inputPosition.SubpassLoad().rgb; - float3 normal = inputNormal.SubpassLoad().rgb; - float4 albedo = inputAlbedo.SubpassLoad(); - - #define ambient 0.05 - - // Ambient part - float3 fragcolor = albedo.rgb * ambient; - - uint lightsLength; - uint lightsStride; - lights.GetDimensions(lightsLength, lightsStride); - - for(int i = 0; i < lightsLength; ++i) - { - float3 L = lights[i].position.xyz - fragPos; - float dist = length(L); - - L = normalize(L); - - float atten = lights[i].radius / (pow(dist, 3.0) + 1.0); - float3 N = normalize(normal); - float NdotL = max(0.0, dot(N, L)); - float3 diff = lights[i].color * albedo.rgb * NdotL * atten; - - fragcolor += diff; - } - - return float4(fragcolor, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/subpasses/composition.vert.spv b/shaders/slang/subpasses/composition.vert.spv deleted file mode 100644 index ef2e0e8e..00000000 Binary files a/shaders/slang/subpasses/composition.vert.spv and /dev/null differ diff --git a/shaders/slang/subpasses/gbuffer.frag.spv b/shaders/slang/subpasses/gbuffer.frag.spv deleted file mode 100644 index 2afaed32..00000000 Binary files a/shaders/slang/subpasses/gbuffer.frag.spv and /dev/null differ diff --git a/shaders/slang/subpasses/gbuffer.slang b/shaders/slang/subpasses/gbuffer.slang deleted file mode 100644 index a648cb31..00000000 --- a/shaders/slang/subpasses/gbuffer.slang +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Color; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float3 WorldPos; - float3 Tangent; -}; - -struct FSOutput -{ - float4 Color : SV_TARGET0; - float4 Position : SV_TARGET1; - float4 Normal : SV_TARGET2; - float4 Albedo : SV_TARGET3; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; -}; -ConstantBuffer ubo; - -[[SpecializationConstant]] const float NEAR_PLANE = 0.1; -[[SpecializationConstant]] const float FAR_PLANE = 256.0; - -float linearDepth(float depth) -{ - float z = depth * 2.0f - 1.0f; - return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE)); -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos))); - // Vertex position in world space - output.WorldPos = mul(ubo.model, input.Pos).xyz; - // GL to Vulkan coord space - output.WorldPos.y = -output.WorldPos.y; - // Normal in world space - output.Normal = mul((float3x3)ubo.model, normalize(input.Normal)); - // Currently just vertex color - output.Color = input.Color; - return output; -} - -[shader("fragment")] -FSOutput fragmentMain(VSOutput input) -{ - FSOutput output; - output.Position = float4(input.WorldPos, 1.0); - float3 N = normalize(input.Normal); - N.y = -N.y; - output.Normal = float4(N, 1.0); - output.Albedo.rgb = input.Color; - // Store linearized depth in alpha component - output.Position.a = linearDepth(input.Pos.z); - // Write color attachments to avoid undefined behaviour (validation error) - output.Color = float4(0.0); - return output; -} \ No newline at end of file diff --git a/shaders/slang/subpasses/gbuffer.vert.spv b/shaders/slang/subpasses/gbuffer.vert.spv deleted file mode 100644 index e3ba7309..00000000 Binary files a/shaders/slang/subpasses/gbuffer.vert.spv and /dev/null differ diff --git a/shaders/slang/subpasses/transparent.frag.spv b/shaders/slang/subpasses/transparent.frag.spv deleted file mode 100644 index d9fbe6c3..00000000 Binary files a/shaders/slang/subpasses/transparent.frag.spv and /dev/null differ diff --git a/shaders/slang/subpasses/transparent.slang b/shaders/slang/subpasses/transparent.slang deleted file mode 100644 index 846e5c6d..00000000 --- a/shaders/slang/subpasses/transparent.slang +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Color; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Color; - float2 UV; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 view; -}; -ConstantBuffer ubo; - -[[vk::input_attachment_index(0)]] SubpassInput samplerPositionDepth; - -Sampler2D samplerTexture; - -[[SpecializationConstant]] const float NEAR_PLANE = 0.1f; -[[SpecializationConstant]] const float FAR_PLANE = 256.0f; - -float linearDepth(float depth) -{ - float z = depth * 2.0f - 1.0f; - return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE)); -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain (VSOutput input) -{ - // Sample depth from deferred depth buffer and discard if obscured - float depth = samplerPositionDepth.SubpassLoad().a; - if ((depth != 0.0) && (linearDepth(input.Pos.z) > depth)) - { - clip(-1); - }; - - return samplerTexture.Sample(input.UV); -} diff --git a/shaders/slang/subpasses/transparent.vert.spv b/shaders/slang/subpasses/transparent.vert.spv deleted file mode 100644 index aea9ddf8..00000000 Binary files a/shaders/slang/subpasses/transparent.vert.spv and /dev/null differ diff --git a/shaders/slang/terraintessellation/skysphere.frag.spv b/shaders/slang/terraintessellation/skysphere.frag.spv deleted file mode 100644 index 2cfde97d..00000000 Binary files a/shaders/slang/terraintessellation/skysphere.frag.spv and /dev/null differ diff --git a/shaders/slang/terraintessellation/skysphere.slang b/shaders/slang/terraintessellation/skysphere.slang deleted file mode 100644 index 1d11ad44..00000000 --- a/shaders/slang/terraintessellation/skysphere.slang +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -struct UBO -{ - float4x4 mvp; -}; -ConstantBuffer ubo; - -Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = mul(ubo.mvp, float4(input.Pos, 1.0)); - output.UV = input.UV; - return output; -} - - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerColorMap.Sample(input.UV); -} diff --git a/shaders/slang/terraintessellation/skysphere.vert.spv b/shaders/slang/terraintessellation/skysphere.vert.spv deleted file mode 100644 index 982ccc80..00000000 Binary files a/shaders/slang/terraintessellation/skysphere.vert.spv and /dev/null differ diff --git a/shaders/slang/terraintessellation/terrain.frag.spv b/shaders/slang/terraintessellation/terrain.frag.spv deleted file mode 100644 index 31b8a9a6..00000000 Binary files a/shaders/slang/terraintessellation/terrain.frag.spv and /dev/null differ diff --git a/shaders/slang/terraintessellation/terrain.slang b/shaders/slang/terraintessellation/terrain.slang deleted file mode 100644 index ad9d475e..00000000 --- a/shaders/slang/terraintessellation/terrain.slang +++ /dev/null @@ -1,252 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; -}; - -struct DSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; - float3 ViewVec; - float3 LightVec; - float3 EyePos; - float3 WorldPos; -}; - -struct UBO -{ - float4x4 projection; - float4x4 modelview; - float4 lightPos; - float4 frustumPlanes[6]; - float displacementFactor; - float tessellationFactor; - float2 viewportDim; - float tessellatedEdgeSize; -}; -ConstantBuffer ubo; - -Sampler2D samplerHeight; -Sampler2DArray samplerLayers; - -struct HSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal : NORMAL0; - float2 UV : TEXCOORD0; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[4] : SV_TessFactor; - float TessLevelInner[2] : SV_InsideTessFactor; -}; - -// Calculate the tessellation factor based on screen space -// dimensions of the edge -float screenSpaceTessFactor(float4 p0, float4 p1) -{ - // Calculate edge mid point - float4 midPoint = 0.5 * (p0 + p1); - // Sphere radius as distance between the control points - float radius = distance(p0, p1) / 2.0; - - // View space - float4 v0 = mul(ubo.modelview, midPoint); - - // Project into clip space - float4 clip0 = mul(ubo.projection, (v0 - float4(radius, float3(0.0, 0.0, 0.0)))); - float4 clip1 = mul(ubo.projection, (v0 + float4(radius, float3(0.0, 0.0, 0.0)))); - - // Get normalized device coordinates - clip0 /= clip0.w; - clip1 /= clip1.w; - - // Convert to viewport coordinates - clip0.xy *= ubo.viewportDim; - clip1.xy *= ubo.viewportDim; - - // Return the tessellation factor based on the screen size - // given by the distance of the two edge control points in screen space - // and a reference (min.) tessellation size for the edge set by the application - return clamp(distance(clip0, clip1) / ubo.tessellatedEdgeSize * ubo.tessellationFactor, 1.0, 64.0); -} - -// Checks the current's patch visibility against the frustum using a sphere check -// Sphere radius is given by the patch size -bool frustumCheck(float4 Pos, float2 inUV) -{ - // Fixed radius (increase if patch size is increased in example) - const float radius = 8.0f; - float4 pos = Pos; - pos.y -= samplerHeight.SampleLevel(inUV, 0.0).r * ubo.displacementFactor; - - // Check sphere against frustum planes - for (int i = 0; i < 6; i++) { - if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0) - { - return false; - } - } - return true; -} - -ConstantsHSOutput ConstantsHS(InputPatch patch) -{ - ConstantsHSOutput output; - - if (!frustumCheck(patch[0].Pos, patch[0].UV)) - { - output.TessLevelInner[0] = 0.0; - output.TessLevelInner[1] = 0.0; - output.TessLevelOuter[0] = 0.0; - output.TessLevelOuter[1] = 0.0; - output.TessLevelOuter[2] = 0.0; - output.TessLevelOuter[3] = 0.0; - } - else - { - if (ubo.tessellationFactor > 0.0) - { - output.TessLevelOuter[0] = screenSpaceTessFactor(patch[3].Pos, patch[0].Pos); - output.TessLevelOuter[1] = screenSpaceTessFactor(patch[0].Pos, patch[1].Pos); - output.TessLevelOuter[2] = screenSpaceTessFactor(patch[1].Pos, patch[2].Pos); - output.TessLevelOuter[3] = screenSpaceTessFactor(patch[2].Pos, patch[3].Pos); - output.TessLevelInner[0] = lerp(output.TessLevelOuter[0], output.TessLevelOuter[3], 0.5); - output.TessLevelInner[1] = lerp(output.TessLevelOuter[2], output.TessLevelOuter[1], 0.5); - } - else - { - // Tessellation factor can be set to zero by example - // to demonstrate a simple passthrough - output.TessLevelInner[0] = 1.0; - output.TessLevelInner[1] = 1.0; - output.TessLevelOuter[0] = 1.0; - output.TessLevelOuter[1] = 1.0; - output.TessLevelOuter[2] = 1.0; - output.TessLevelOuter[3] = 1.0; - } - } - - return output; -} - -float3 sampleTerrainLayer(float2 inUV) -{ - // Define some layer ranges for sampling depending on terrain height - float2 layers[6]; - layers[0] = float2(-10.0, 10.0); - layers[1] = float2(5.0, 45.0); - layers[2] = float2(45.0, 80.0); - layers[3] = float2(75.0, 100.0); - layers[4] = float2(95.0, 140.0); - layers[5] = float2(140.0, 190.0); - - float3 color = float3(0.0, 0.0, 0.0); - - // Get height from displacement map - float height = samplerHeight.SampleLevel(inUV, 0.0).r * 255.0; - - for (int i = 0; i < 6; i++) - { - float range = layers[i].y - layers[i].x; - float weight = (range - abs(height - layers[i].y)) / range; - weight = max(0.0, weight); - color += weight * samplerLayers.Sample(float3(inUV * 16.0, i)).rgb; - } - - return color; -} - -float fog(float density, float4 FragCoord) -{ - const float LOG2 = -1.442695; - float dist = FragCoord.z / FragCoord.w * 0.1; - float d = density * dist; - return 1.0 - clamp(exp2(d * d * LOG2), 0.0, 1.0); -} - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = float4(input.Pos.xyz, 1.0); - output.UV = input.UV; - output.Normal = input.Normal; - return output; -} - -[shader("hull")] -[domain("quad")] -[partitioning("integer")] -[outputtopology("triangle_cw")] -[outputcontrolpoints(4)] -[patchconstantfunc("ConstantsHS")] -[maxtessfactor(20.0f)] -HSOutput hullMain(InputPatch patch, uint InvocationID: SV_OutputControlPointID) -{ - HSOutput output; - output.Pos = patch[InvocationID].Pos; - output.Normal = patch[InvocationID].Normal; - output.UV = patch[InvocationID].UV; - return output; -} - -[shader("domain")] -[domain("quad")] -DSOutput domainMain(ConstantsHSOutput input, float2 TessCoord: SV_DomainLocation, const OutputPatch patch) -{ - // Interpolate UV coordinates - DSOutput output; - float2 uv1 = lerp(patch[0].UV, patch[1].UV, TessCoord.x); - float2 uv2 = lerp(patch[3].UV, patch[2].UV, TessCoord.x); - output.UV = lerp(uv1, uv2, TessCoord.y); - - float3 n1 = lerp(patch[0].Normal, patch[1].Normal, TessCoord.x); - float3 n2 = lerp(patch[3].Normal, patch[2].Normal, TessCoord.x); - output.Normal = lerp(n1, n2, TessCoord.y); - - // Interpolate positions - float4 pos1 = lerp(patch[0].Pos, patch[1].Pos, TessCoord.x); - float4 pos2 = lerp(patch[3].Pos, patch[2].Pos, TessCoord.x); - float4 pos = lerp(pos1, pos2, TessCoord.y); - // Displace - pos.y -= samplerHeight.SampleLevel(output.UV, 0.0).r * ubo.displacementFactor; - // Perspective projection - output.Pos = mul(ubo.projection, mul(ubo.modelview, pos)); - - // Calculate vectors for lighting based on tessellated position - output.ViewVec = -pos.xyz; - output.LightVec = normalize(ubo.lightPos.xyz + output.ViewVec); - output.WorldPos = pos.xyz; - output.EyePos = mul(ubo.modelview, pos).xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(DSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 ambient = float3(0.5, 0.5, 0.5); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float4 color = float4((ambient + diffuse) * sampleTerrainLayer(input.UV), 1.0); - const float4 fogColor = float4(0.47, 0.5, 0.67, 0.0); - return lerp(color, fogColor, fog(0.25, input.Pos)); -} diff --git a/shaders/slang/terraintessellation/terrain.tesc.spv b/shaders/slang/terraintessellation/terrain.tesc.spv deleted file mode 100644 index e51394a5..00000000 Binary files a/shaders/slang/terraintessellation/terrain.tesc.spv and /dev/null differ diff --git a/shaders/slang/terraintessellation/terrain.tese.spv b/shaders/slang/terraintessellation/terrain.tese.spv deleted file mode 100644 index 490be63b..00000000 Binary files a/shaders/slang/terraintessellation/terrain.tese.spv and /dev/null differ diff --git a/shaders/slang/terraintessellation/terrain.vert.spv b/shaders/slang/terraintessellation/terrain.vert.spv deleted file mode 100644 index b50c5a1e..00000000 Binary files a/shaders/slang/terraintessellation/terrain.vert.spv and /dev/null differ diff --git a/shaders/slang/tessellation/base.frag.spv b/shaders/slang/tessellation/base.frag.spv deleted file mode 100644 index 19395722..00000000 Binary files a/shaders/slang/tessellation/base.frag.spv and /dev/null differ diff --git a/shaders/slang/tessellation/base.slang b/shaders/slang/tessellation/base.slang deleted file mode 100644 index e671b8df..00000000 --- a/shaders/slang/tessellation/base.slang +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; -}; - -struct DSOutput -{ - float3 Normal; - float2 UV; -}; - -[[vk::binding(0, 1)]] Sampler2D samplerColorMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = float4(input.Pos.xyz, 1.0); - output.Normal = input.Normal; - output.UV = input.UV; - return output; -} - -[shader("fragment")] -float4 fragmentMain(DSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(float3(0.0, -4.0, 4.0)); - float4 color = samplerColorMap.Sample(input.UV); - return float4(clamp(max(dot(N,L), 0.0), 0.2, 1.0) * color.rgb * 1.5, 1); -} diff --git a/shaders/slang/tessellation/base.vert.spv b/shaders/slang/tessellation/base.vert.spv deleted file mode 100644 index b50c5a1e..00000000 Binary files a/shaders/slang/tessellation/base.vert.spv and /dev/null differ diff --git a/shaders/slang/tessellation/passthrough.slang b/shaders/slang/tessellation/passthrough.slang deleted file mode 100644 index b25454e7..00000000 --- a/shaders/slang/tessellation/passthrough.slang +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; -}; - -struct HSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; -}; - -struct DSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner[2] : SV_InsideTessFactor; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float tessAlpha; - float tessLevel; -}; -ConstantBuffer ubo; - -ConstantsHSOutput ConstantsHS(InputPatch patch) -{ - ConstantsHSOutput output; - output.TessLevelInner[0] = 1; - output.TessLevelInner[1] = 1; - output.TessLevelOuter[0] = 1; - output.TessLevelOuter[1] = 1; - output.TessLevelOuter[2] = 1; - return output; -} - -[shader("hull")] -[domain("tri")] -[partitioning("integer")] -[outputtopology("triangle_cw")] -[outputcontrolpoints(3)] -[patchconstantfunc("ConstantsHS")] -[maxtessfactor(20.0f)] -HSOutput hullMain(InputPatch patch, uint InvocationID : SV_OutputControlPointID) -{ - HSOutput output; - output.Pos = patch[InvocationID].Pos; - output.Normal = patch[InvocationID].Normal; - output.UV = patch[InvocationID].UV; - return output; -} - -[shader("domain")] -[domain("tri")] -DSOutput domainMain(ConstantsHSOutput input, float3 TessCoord: SV_DomainLocation, const OutputPatch patch) -{ - DSOutput output = (DSOutput)0; - output.Pos = (TessCoord.x * patch[0].Pos) + - (TessCoord.y * patch[1].Pos) + - (TessCoord.z * patch[2].Pos); - output.Pos = mul(ubo.projection, mul(ubo.model, output.Pos)); - - output.Normal = TessCoord.x * patch[0].Normal + TessCoord.y * patch[1].Normal + TessCoord.z * patch[2].Normal; - output.UV = TessCoord.x * patch[0].UV + TessCoord.y * patch[1].UV + TessCoord.z * patch[2].UV; - return output; -} \ No newline at end of file diff --git a/shaders/slang/tessellation/passthrough.tesc.spv b/shaders/slang/tessellation/passthrough.tesc.spv deleted file mode 100644 index 8c59ad09..00000000 Binary files a/shaders/slang/tessellation/passthrough.tesc.spv and /dev/null differ diff --git a/shaders/slang/tessellation/passthrough.tese.spv b/shaders/slang/tessellation/passthrough.tese.spv deleted file mode 100644 index 79673cfa..00000000 Binary files a/shaders/slang/tessellation/passthrough.tese.spv and /dev/null differ diff --git a/shaders/slang/tessellation/pntriangles.slang b/shaders/slang/tessellation/pntriangles.slang deleted file mode 100644 index f1761ff7..00000000 --- a/shaders/slang/tessellation/pntriangles.slang +++ /dev/null @@ -1,216 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; -}; - -struct HSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; - float pnPatch[10]; -}; - -struct DSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; -}; - -struct ConstantsHSOutput -{ - float TessLevelOuter[3] : SV_TessFactor; - float TessLevelInner[2] : SV_InsideTessFactor; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float tessAlpha; - float tessLevel; -}; -ConstantBuffer ubo; - -#define uvw TessCoord - -struct PnPatch -{ - float b210; - float b120; - float b021; - float b012; - float b102; - float b201; - float b111; - float n110; - float n011; - float n101; -}; - -PnPatch GetPnPatch(float pnPatch[10]) -{ - PnPatch output; - output.b210 = pnPatch[0]; - output.b120 = pnPatch[1]; - output.b021 = pnPatch[2]; - output.b012 = pnPatch[3]; - output.b102 = pnPatch[4]; - output.b201 = pnPatch[5]; - output.b111 = pnPatch[6]; - output.n110 = pnPatch[7]; - output.n011 = pnPatch[8]; - output.n101 = pnPatch[9]; - return output; -} - -void SetPnPatch(out float output[10], PnPatch patch) -{ - output[0] = patch.b210; - output[1] = patch.b120; - output[2] = patch.b021; - output[3] = patch.b012; - output[4] = patch.b102; - output[5] = patch.b201; - output[6] = patch.b111; - output[7] = patch.n110; - output[8] = patch.n011; - output[9] = patch.n101; -} - -float wij(float4 iPos, float3 iNormal, float4 jPos) -{ - return dot(jPos.xyz - iPos.xyz, iNormal); -} - -float vij(float4 iPos, float3 iNormal, float4 jPos, float3 jNormal) -{ - float3 Pj_minus_Pi = jPos.xyz - iPos.xyz; - float3 Ni_plus_Nj = iNormal + jNormal; - return 2.0 * dot(Pj_minus_Pi, Ni_plus_Nj) / dot(Pj_minus_Pi, Pj_minus_Pi); -} - -ConstantsHSOutput ConstantsHS(InputPatch patch) -{ - ConstantsHSOutput output; - output.TessLevelOuter[0] = ubo.tessLevel; - output.TessLevelOuter[1] = ubo.tessLevel; - output.TessLevelOuter[2] = ubo.tessLevel; - output.TessLevelInner[0] = ubo.tessLevel; - output.TessLevelInner[1] = ubo.tessLevel; - return output; -} - -[shader("domain")] -[domain("tri")] -DSOutput domainMain(ConstantsHSOutput input, float3 TessCoord: SV_DomainLocation, const OutputPatch patch) -{ - PnPatch pnPatch[3]; - pnPatch[0] = GetPnPatch(patch[0].pnPatch); - pnPatch[1] = GetPnPatch(patch[1].pnPatch); - pnPatch[2] = GetPnPatch(patch[2].pnPatch); - - DSOutput output = (DSOutput)0; - float3 uvwSquared = uvw * uvw; - float3 uvwCubed = uvwSquared * uvw; - - // extract control points - float3 b210 = float3(pnPatch[0].b210, pnPatch[1].b210, pnPatch[2].b210); - float3 b120 = float3(pnPatch[0].b120, pnPatch[1].b120, pnPatch[2].b120); - float3 b021 = float3(pnPatch[0].b021, pnPatch[1].b021, pnPatch[2].b021); - float3 b012 = float3(pnPatch[0].b012, pnPatch[1].b012, pnPatch[2].b012); - float3 b102 = float3(pnPatch[0].b102, pnPatch[1].b102, pnPatch[2].b102); - float3 b201 = float3(pnPatch[0].b201, pnPatch[1].b201, pnPatch[2].b201); - float3 b111 = float3(pnPatch[0].b111, pnPatch[1].b111, pnPatch[2].b111); - - // extract control normals - float3 n110 = normalize(float3(pnPatch[0].n110, pnPatch[1].n110, pnPatch[2].n110)); - float3 n011 = normalize(float3(pnPatch[0].n011, pnPatch[1].n011, pnPatch[2].n011)); - float3 n101 = normalize(float3(pnPatch[0].n101, pnPatch[1].n101, pnPatch[2].n101)); - - // compute texcoords - output.UV = TessCoord[2] * patch[0].UV + TessCoord[0] * patch[1].UV + TessCoord[1] * patch[2].UV; - - // normal - // Barycentric normal - float3 barNormal = TessCoord[2] * patch[0].Normal + TessCoord[0] * patch[1].Normal + TessCoord[1] * patch[2].Normal; - float3 pnNormal = patch[0].Normal * uvwSquared[2] + patch[1].Normal * uvwSquared[0] + patch[2].Normal * uvwSquared[1] - + n110 * uvw[2] * uvw[0] + n011 * uvw[0] * uvw[1] + n101 * uvw[2] * uvw[1]; - output.Normal = ubo.tessAlpha * pnNormal + (1.0 - ubo.tessAlpha) * barNormal; - - // compute interpolated pos - float3 barPos = TessCoord[2] * patch[0].Pos.xyz - + TessCoord[0] * patch[1].Pos.xyz - + TessCoord[1] * patch[2].Pos.xyz; - - // save some computations - uvwSquared *= 3.0; - - // compute PN position - float3 pnPos = patch[0].Pos.xyz * uvwCubed[2] - + patch[1].Pos.xyz * uvwCubed[0] - + patch[2].Pos.xyz * uvwCubed[1] - + b210 * uvwSquared[2] * uvw[0] - + b120 * uvwSquared[0] * uvw[2] - + b201 * uvwSquared[2] * uvw[1] - + b021 * uvwSquared[0] * uvw[1] - + b102 * uvwSquared[1] * uvw[2] - + b012 * uvwSquared[1] * uvw[0] - + b111 * 6.0 * uvw[0] * uvw[1] * uvw[2]; - - // final position and normal - float3 finalPos = (1.0 - ubo.tessAlpha) * barPos + ubo.tessAlpha * pnPos; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(finalPos, 1.0))); - return output; -} - -[shader("hull")] -[domain("tri")] -[partitioning("fractional_odd")] -[outputtopology("triangle_cw")] -[outputcontrolpoints(3)] -[patchconstantfunc("ConstantsHS")] -[maxtessfactor(20.0f)] -HSOutput hullMain(InputPatch patch, uint InvocationID : SV_OutputControlPointID) -{ - HSOutput output; - // get data - output.Pos = patch[InvocationID].Pos; - output.Normal = patch[InvocationID].Normal; - output.UV = patch[InvocationID].UV; - - // set base - float P0 = patch[0].Pos[InvocationID]; - float P1 = patch[1].Pos[InvocationID]; - float P2 = patch[2].Pos[InvocationID]; - float N0 = patch[0].Normal[InvocationID]; - float N1 = patch[1].Normal[InvocationID]; - float N2 = patch[2].Normal[InvocationID]; - - // compute control points - PnPatch pnPatch; - pnPatch.b210 = (2.0*P0 + P1 - wij(patch[0].Pos, patch[0].Normal, patch[1].Pos)*N0)/3.0; - pnPatch.b120 = (2.0*P1 + P0 - wij(patch[1].Pos, patch[1].Normal, patch[0].Pos)*N1)/3.0; - pnPatch.b021 = (2.0*P1 + P2 - wij(patch[1].Pos, patch[1].Normal, patch[2].Pos)*N1)/3.0; - pnPatch.b012 = (2.0*P2 + P1 - wij(patch[2].Pos, patch[2].Normal, patch[1].Pos)*N2)/3.0; - pnPatch.b102 = (2.0*P2 + P0 - wij(patch[2].Pos, patch[2].Normal, patch[0].Pos)*N2)/3.0; - pnPatch.b201 = (2.0*P0 + P2 - wij(patch[0].Pos, patch[0].Normal, patch[2].Pos)*N0)/3.0; - float E = ( pnPatch.b210 + pnPatch.b120 + pnPatch.b021 + pnPatch.b012 + pnPatch.b102 + pnPatch.b201 ) / 6.0; - float V = (P0 + P1 + P2)/3.0; - pnPatch.b111 = E + (E - V)*0.5; - pnPatch.n110 = N0+N1-vij(patch[0].Pos, patch[0].Normal, patch[1].Pos, patch[1].Normal)*(P1-P0); - pnPatch.n011 = N1+N2-vij(patch[1].Pos, patch[1].Normal, patch[2].Pos, patch[2].Normal)*(P2-P1); - pnPatch.n101 = N2+N0-vij(patch[2].Pos, patch[2].Normal, patch[0].Pos, patch[0].Normal)*(P0-P2); - SetPnPatch(output.pnPatch, pnPatch); - - return output; -} \ No newline at end of file diff --git a/shaders/slang/tessellation/pntriangles.tesc.spv b/shaders/slang/tessellation/pntriangles.tesc.spv deleted file mode 100644 index 21b7dd7e..00000000 Binary files a/shaders/slang/tessellation/pntriangles.tesc.spv and /dev/null differ diff --git a/shaders/slang/tessellation/pntriangles.tese.spv b/shaders/slang/tessellation/pntriangles.tese.spv deleted file mode 100644 index 7322860d..00000000 Binary files a/shaders/slang/tessellation/pntriangles.tese.spv and /dev/null differ diff --git a/shaders/slang/textoverlay/mesh.frag.spv b/shaders/slang/textoverlay/mesh.frag.spv deleted file mode 100644 index 396c7f8e..00000000 Binary files a/shaders/slang/textoverlay/mesh.frag.spv and /dev/null differ diff --git a/shaders/slang/textoverlay/mesh.slang b/shaders/slang/textoverlay/mesh.slang deleted file mode 100644 index a7c4d07d..00000000 --- a/shaders/slang/textoverlay/mesh.slang +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 lightPos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.UV = input.UV; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, normalize(input.Normal)); - float3 lPos = mul((float3x3)ubo.model, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float diffuse = max(dot(N, L), 0.0); - float specular = pow(max(dot(R, V), 0.0), 1.0); - return float4(((diffuse + specular) * 0.25).xxx, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/textoverlay/mesh.vert.spv b/shaders/slang/textoverlay/mesh.vert.spv deleted file mode 100644 index dce7a391..00000000 Binary files a/shaders/slang/textoverlay/mesh.vert.spv and /dev/null differ diff --git a/shaders/slang/textoverlay/text.frag.spv b/shaders/slang/textoverlay/text.frag.spv deleted file mode 100644 index c1aa8731..00000000 Binary files a/shaders/slang/textoverlay/text.frag.spv and /dev/null differ diff --git a/shaders/slang/textoverlay/text.slang b/shaders/slang/textoverlay/text.slang deleted file mode 100644 index f4ca9337..00000000 --- a/shaders/slang/textoverlay/text.slang +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - - struct VSInput -{ - float2 Pos; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; -}; - -Sampler2D samplerFont; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = float4(input.Pos, 0.0, 1.0); - output.UV = input.UV; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float color = samplerFont.Sample(input.UV).r; - return color.xxxx; -} diff --git a/shaders/slang/textoverlay/text.vert.spv b/shaders/slang/textoverlay/text.vert.spv deleted file mode 100644 index 79269cc0..00000000 Binary files a/shaders/slang/textoverlay/text.vert.spv and /dev/null differ diff --git a/shaders/slang/texture/texture.frag.spv b/shaders/slang/texture/texture.frag.spv deleted file mode 100644 index 5a369ab8..00000000 Binary files a/shaders/slang/texture/texture.frag.spv and /dev/null differ diff --git a/shaders/slang/texture/texture.slang b/shaders/slang/texture/texture.slang deleted file mode 100644 index 8c104e10..00000000 --- a/shaders/slang/texture/texture.slang +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float LodBias; - float3 Normal; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 viewPos; - float lodBias; -}; -ConstantBuffer ubo; - -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - output.LodBias = ubo.lodBias; - - float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lightPos = float3(0.0, 0.0, 0.0); - float3 lPos = mul((float3x3)ubo.model, lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerColor.SampleLevel(input.UV, input.LodBias); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a; - - return float4(diffuse * color.rgb + specular, 1.0); -} diff --git a/shaders/slang/texture/texture.vert.spv b/shaders/slang/texture/texture.vert.spv deleted file mode 100644 index b58e6baa..00000000 Binary files a/shaders/slang/texture/texture.vert.spv and /dev/null differ diff --git a/shaders/slang/texture3d/texture3d.frag.spv b/shaders/slang/texture3d/texture3d.frag.spv deleted file mode 100644 index 74241b57..00000000 Binary files a/shaders/slang/texture3d/texture3d.frag.spv and /dev/null differ diff --git a/shaders/slang/texture3d/texture3d.slang b/shaders/slang/texture3d/texture3d.slang deleted file mode 100644 index c11208b9..00000000 --- a/shaders/slang/texture3d/texture3d.slang +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UV; - float3 Normal; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 viewPos; - float depth; -}; -ConstantBuffer ubo; - -Sampler3D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = float3(input.UV, ubo.depth); - - float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lightPos = float3(0.0, 0.0, 0.0); - float3 lPos = mul((float3x3)ubo.model, lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = samplerColor.Sample(input.UV); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.r; - - return float4(diffuse * color.r + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/texture3d/texture3d.vert.spv b/shaders/slang/texture3d/texture3d.vert.spv deleted file mode 100644 index 65dc9c3c..00000000 Binary files a/shaders/slang/texture3d/texture3d.vert.spv and /dev/null differ diff --git a/shaders/slang/texturearray/instancing.frag.spv b/shaders/slang/texturearray/instancing.frag.spv deleted file mode 100644 index ed7507bf..00000000 Binary files a/shaders/slang/texturearray/instancing.frag.spv and /dev/null differ diff --git a/shaders/slang/texturearray/instancing.slang b/shaders/slang/texturearray/instancing.slang deleted file mode 100644 index 6db77ac9..00000000 --- a/shaders/slang/texturearray/instancing.slang +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UV; -}; - -struct Instance -{ - float4x4 model; - float arrayIndex; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - Instance instance[8]; -}; -ConstantBuffer ubo; - -Sampler2DArray samplerArray; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uint InstanceIndex: SV_InstanceID) -{ - VSOutput output; - output.UV = float3(input.UV, ubo.instance[InstanceIndex].arrayIndex); - float4x4 modelView = mul(ubo.view, ubo.instance[InstanceIndex].model); - output.Pos = mul(ubo.projection, mul(modelView, float4(input.Pos, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerArray.Sample(input.UV); -} \ No newline at end of file diff --git a/shaders/slang/texturearray/instancing.vert.spv b/shaders/slang/texturearray/instancing.vert.spv deleted file mode 100644 index 14880373..00000000 Binary files a/shaders/slang/texturearray/instancing.vert.spv and /dev/null differ diff --git a/shaders/slang/texturecubemap/reflect.frag.spv b/shaders/slang/texturecubemap/reflect.frag.spv deleted file mode 100644 index 203a318c..00000000 Binary files a/shaders/slang/texturecubemap/reflect.frag.spv and /dev/null differ diff --git a/shaders/slang/texturecubemap/reflect.slang b/shaders/slang/texturecubemap/reflect.slang deleted file mode 100644 index f938523b..00000000 --- a/shaders/slang/texturecubemap/reflect.slang +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 WorldPos; - float3 Normal; - float LodBias; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 invModel; - float lodBias; -}; -ConstantBuffer ubo; - -SamplerCube samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - output.WorldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.Normal = mul((float3x3)ubo.model, input.Normal); - output.LodBias = ubo.lodBias; - - float3 lightPos = float3(0.0f, -5.0f, 5.0f); - output.LightVec = lightPos.xyz - output.WorldPos.xyz; - output.ViewVec = -output.WorldPos; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 cI = normalize (input.ViewVec); - float3 cR = reflect (cI, normalize(input.Normal)); - - cR = mul(ubo.invModel, float4(cR, 0.0)).xyz; - // Convert cubemap coordinates into Vulkan coordinate space - cR.z *= -1.0; - - float4 color = samplerColor.SampleLevel(cR, input.LodBias); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.5, 0.5, 0.5) * color.rgb; - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.5, 0.5, 0.5); - return float4(ambient + diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/texturecubemap/reflect.vert.spv b/shaders/slang/texturecubemap/reflect.vert.spv deleted file mode 100644 index e915ac45..00000000 Binary files a/shaders/slang/texturecubemap/reflect.vert.spv and /dev/null differ diff --git a/shaders/slang/texturecubemap/skybox.frag.spv b/shaders/slang/texturecubemap/skybox.frag.spv deleted file mode 100644 index 71e6a035..00000000 Binary files a/shaders/slang/texturecubemap/skybox.frag.spv and /dev/null differ diff --git a/shaders/slang/texturecubemap/skybox.slang b/shaders/slang/texturecubemap/skybox.slang deleted file mode 100644 index 618fb2f3..00000000 --- a/shaders/slang/texturecubemap/skybox.slang +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; -}; -ConstantBuffer ubo; - -SamplerCube samplerCubeMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UVW = input.Pos; - // Convert cubemap coordinates into Vulkan coordinate space - output.UVW.xy *= -1.0; - // Remove translation from view matrix - float4x4 viewMat = ubo.model; - viewMat[0][3] = 0.0; - viewMat[1][3] = 0.0; - viewMat[2][3] = 0.0; - output.Pos = mul(ubo.projection, mul(viewMat, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerCubeMap.Sample(input.UVW); -} \ No newline at end of file diff --git a/shaders/slang/texturecubemap/skybox.vert.spv b/shaders/slang/texturecubemap/skybox.vert.spv deleted file mode 100644 index b7c2316f..00000000 Binary files a/shaders/slang/texturecubemap/skybox.vert.spv and /dev/null differ diff --git a/shaders/slang/texturecubemaparray/reflect.frag.spv b/shaders/slang/texturecubemaparray/reflect.frag.spv deleted file mode 100644 index 84d4c6b8..00000000 Binary files a/shaders/slang/texturecubemaparray/reflect.frag.spv and /dev/null differ diff --git a/shaders/slang/texturecubemaparray/reflect.slang b/shaders/slang/texturecubemaparray/reflect.slang deleted file mode 100644 index 1edb34b3..00000000 --- a/shaders/slang/texturecubemaparray/reflect.slang +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 WorldPos; - float3 Normal; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 invModel; - float lodBias; - int cubeMapIndex; -}; -ConstantBuffer ubo; - -SamplerCubeArray samplerCubeMapArray; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - - output.WorldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - output.Normal = mul((float3x3)ubo.model, input.Normal); - - float3 lightPos = float3(0.0f, -5.0f, 5.0f); - output.LightVec = lightPos.xyz - output.WorldPos.xyz; - output.ViewVec = -output.WorldPos; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 cI = normalize(input.WorldPos.xyz); - float3 cR = reflect(cI, normalize(input.Normal)); - - cR = mul(ubo.invModel, float4(cR, 0.0)).xyz; - cR.yz *= -1.0; - - float4 color = samplerCubeMapArray.SampleLevel(float4(cR, ubo.cubeMapIndex), ubo.lodBias); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.5, 0.5, 0.5) * color.rgb; - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.5, 0.5, 0.5); - return float4(ambient + diffuse * color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/texturecubemaparray/reflect.vert.spv b/shaders/slang/texturecubemaparray/reflect.vert.spv deleted file mode 100644 index 807b6cf9..00000000 Binary files a/shaders/slang/texturecubemaparray/reflect.vert.spv and /dev/null differ diff --git a/shaders/slang/texturecubemaparray/skybox.frag.spv b/shaders/slang/texturecubemaparray/skybox.frag.spv deleted file mode 100644 index b03c534b..00000000 Binary files a/shaders/slang/texturecubemaparray/skybox.frag.spv and /dev/null differ diff --git a/shaders/slang/texturecubemaparray/skybox.slang b/shaders/slang/texturecubemaparray/skybox.slang deleted file mode 100644 index f7686993..00000000 --- a/shaders/slang/texturecubemaparray/skybox.slang +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 invModel; - float lodBias; - int cubeMapIndex; -}; -ConstantBuffer ubo; - -SamplerCubeArray samplerCubeMapArray; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UVW = input.Pos; - output.UVW.xy *= -1.0; - // Remove translation from view matrix - float4x4 viewMat = ubo.model; - viewMat[0][3] = 0.0; - viewMat[1][3] = 0.0; - viewMat[2][3] = 0.0; - output.Pos = mul(ubo.projection, mul(viewMat, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerCubeMapArray.SampleLevel(float4(input.UVW, ubo.cubeMapIndex), ubo.lodBias); -} \ No newline at end of file diff --git a/shaders/slang/texturecubemaparray/skybox.vert.spv b/shaders/slang/texturecubemaparray/skybox.vert.spv deleted file mode 100644 index e5c3dd2b..00000000 Binary files a/shaders/slang/texturecubemaparray/skybox.vert.spv and /dev/null differ diff --git a/shaders/slang/texturemipmapgen/texture.frag.spv b/shaders/slang/texturemipmapgen/texture.frag.spv deleted file mode 100644 index 14c85ad7..00000000 Binary files a/shaders/slang/texturemipmapgen/texture.frag.spv and /dev/null differ diff --git a/shaders/slang/texturemipmapgen/texture.slang b/shaders/slang/texturemipmapgen/texture.slang deleted file mode 100644 index 41aaca50..00000000 --- a/shaders/slang/texturemipmapgen/texture.slang +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float2 UV; - float3 Normal; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float LodBias; - float3 Normal; - float3 ViewVec; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 viewPos; - float lodBias; - int samplerIndex; -}; -ConstantBuffer ubo; - -Texture2D textureColor; -SamplerState samplers[3]; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV * float2(2.0, 1.0); - output.LodBias = ubo.lodBias; - - float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; - - output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - - output.Normal = mul((float3x3)ubo.model, input.Normal); - float3 lightPos = float3(-30.0, 0.0, 0.0); - output.LightVec = worldPos - lightPos; - output.ViewVec = ubo.viewPos.xyz - worldPos; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float4 color = textureColor.Sample(samplers[ubo.samplerIndex], input.UV, int2(0, 0), input.LodBias); - - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(L, N); - float3 diffuse = max(dot(N, L), 0.65) * float3(1.0, 1.0, 1.0); - float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a; - return float4(diffuse * color.r + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/texturemipmapgen/texture.vert.spv b/shaders/slang/texturemipmapgen/texture.vert.spv deleted file mode 100644 index 0a076113..00000000 Binary files a/shaders/slang/texturemipmapgen/texture.vert.spv and /dev/null differ diff --git a/shaders/slang/texturesparseresidency/sparseresidency.frag.spv b/shaders/slang/texturesparseresidency/sparseresidency.frag.spv deleted file mode 100644 index 0ea3e400..00000000 Binary files a/shaders/slang/texturesparseresidency/sparseresidency.frag.spv and /dev/null differ diff --git a/shaders/slang/texturesparseresidency/sparseresidency.slang b/shaders/slang/texturesparseresidency/sparseresidency.slang deleted file mode 100644 index 6ad26c8a..00000000 --- a/shaders/slang/texturesparseresidency/sparseresidency.slang +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float LodBias; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4 viewPos; - float lodBias; -}; -ConstantBuffer ubo; - -Sampler2D samplerColor; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.UV; - output.LodBias = ubo.lodBias; - output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - // Check if texel is resident - uint status = 0; - float4 sampledColor = samplerColor.Sample(input.UV, int2(0, 0), input.LodBias, status); - bool texelResident = CheckAccessFullyMapped(status); - if (texelResident) { - return sampledColor; - } else { - return float4(0.0, 0.0, 0.0, 1.0); - } -} \ No newline at end of file diff --git a/shaders/slang/texturesparseresidency/sparseresidency.vert.spv b/shaders/slang/texturesparseresidency/sparseresidency.vert.spv deleted file mode 100644 index 784b20dd..00000000 Binary files a/shaders/slang/texturesparseresidency/sparseresidency.vert.spv and /dev/null differ diff --git a/shaders/slang/triangle/triangle.frag.spv b/shaders/slang/triangle/triangle.frag.spv deleted file mode 100644 index 81761f27..00000000 Binary files a/shaders/slang/triangle/triangle.frag.spv and /dev/null differ diff --git a/shaders/slang/triangle/triangle.slang b/shaders/slang/triangle/triangle.slang deleted file mode 100644 index b403786f..00000000 --- a/shaders/slang/triangle/triangle.slang +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct UBO -{ - float4x4 projectionMatrix; - float4x4 modelMatrix; - float4x4 viewMatrix; -}; -[[vk::binding(0, 0)]] -ConstantBuffer ubo; - -struct VSInput -{ - [[vk::location(0)]] float3 Pos; - [[vk::location(1)]] float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - [[vk::location(0)]] float3 Color; -}; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Pos = mul(ubo.projectionMatrix, mul(ubo.viewMatrix, mul(ubo.modelMatrix, float4(input.Pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return float4(input.Color, 1.0); -} diff --git a/shaders/slang/triangle/triangle.vert.spv b/shaders/slang/triangle/triangle.vert.spv deleted file mode 100644 index b3fefe85..00000000 Binary files a/shaders/slang/triangle/triangle.vert.spv and /dev/null differ diff --git a/shaders/slang/variablerateshading/scene.frag.spv b/shaders/slang/variablerateshading/scene.frag.spv deleted file mode 100644 index 8d3b3031..00000000 Binary files a/shaders/slang/variablerateshading/scene.frag.spv and /dev/null differ diff --git a/shaders/slang/variablerateshading/scene.slang b/shaders/slang/variablerateshading/scene.slang deleted file mode 100644 index e5954740..00000000 --- a/shaders/slang/variablerateshading/scene.slang +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float3 Color; - float4 Tangent; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; - float2 UV; - float3 ViewVec; - float3 LightVec; - float4 Tangent; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4x4 model; - float4 lightPos; - float4 viewPos; - int colorShadingRates; -}; -ConstantBuffer ubo; - -[[vk::binding(0, 1)]] Sampler2D samplerColorMap; -[[vk::binding(1, 1)]] Sampler2D samplerNormalMap; - -[[SpecializationConstant]] const bool ALPHA_MASK = false; -[[SpecializationConstant]] const float ALPHA_MASK_CUTOFF = 0.0; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Normal = input.Normal; - output.Color = input.Color; - output.UV = input.UV; - output.Tangent = input.Tangent; - - float4x4 modelView = mul(ubo.view, ubo.model); - - output.Pos = mul(ubo.projection, mul(modelView, float4(input.Pos.xyz, 1.0))); - - output.Normal = mul((float3x3)ubo.model, input.Normal); - float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} - -static const uint SHADING_RATE_PER_PIXEL = 0; -static const uint SHADING_RATE_PER_2X1_PIXELS = 6; -static const uint SHADING_RATE_PER_1X2_PIXELS = 7; -static const uint SHADING_RATE_PER_2X2_PIXELS = 8; -static const uint SHADING_RATE_PER_4X2_PIXELS = 9; -static const uint SHADING_RATE_PER_2X4_PIXELS = 10; - -[shader("fragment")] -float4 fragmentMain(VSOutput input, uint shadingRate : SV_ShadingRate) -{ - float4 color = samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); - - if (ALPHA_MASK) { - if (color.a < ALPHA_MASK_CUTOFF) { - discard; - } - } - - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent.xyz); - float3 B = cross(input.Normal, input.Tangent.xyz) * input.Tangent.w; - float3x3 TBN = float3x3(T, B, N); - N = mul(normalize(samplerNormalMap.Sample(input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - - const float ambient = 0.1; - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), ambient).rrr; - float3 specular = pow(max(dot(R, V), 0.0), 32.0); - color = float4(diffuse * color.rgb + specular, color.a); - - if (ubo.colorShadingRates == 1) { - switch (shadingRate) { - case SHADING_RATE_PER_PIXEL: - return color * float4(0.0, 0.8, 0.4, 1.0); - case SHADING_RATE_PER_2X1_PIXELS: - return color * float4(0.2, 0.6, 1.0, 1.0); - case SHADING_RATE_PER_1X2_PIXELS: - return color * float4(0.0, 0.4, 0.8, 1.0); - case SHADING_RATE_PER_2X2_PIXELS: - return color * float4(1.0, 1.0, 0.2, 1.0); - case SHADING_RATE_PER_4X2_PIXELS: - return color * float4(0.8, 0.8, 0.0, 1.0); - case SHADING_RATE_PER_2X4_PIXELS: - return color * float4(1.0, 0.4, 0.2, 1.0); - default: - return color * float4(0.8, 0.0, 0.0, 1.0); - } - } - - return color; -} \ No newline at end of file diff --git a/shaders/slang/variablerateshading/scene.vert.spv b/shaders/slang/variablerateshading/scene.vert.spv deleted file mode 100644 index 4b157a51..00000000 Binary files a/shaders/slang/variablerateshading/scene.vert.spv and /dev/null differ diff --git a/shaders/slang/vertexattributes/scene.frag.spv b/shaders/slang/vertexattributes/scene.frag.spv deleted file mode 100644 index 85b56edf..00000000 Binary files a/shaders/slang/vertexattributes/scene.frag.spv and /dev/null differ diff --git a/shaders/slang/vertexattributes/scene.slang b/shaders/slang/vertexattributes/scene.slang deleted file mode 100644 index 39223e4e..00000000 --- a/shaders/slang/vertexattributes/scene.slang +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float2 UV; - float4 Tangent; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float2 UV; - float3 ViewVec; - float3 LightVec; - float4 Tangent; -}; - -struct UBO -{ - float4x4 projection; - float4x4 view; - float4 lightPos; - float4 viewPos; -}; -ConstantBuffer ubo; - -[[vk::binding(0, 1)]] Sampler2D samplerColorMap; -[[vk::binding(1, 1)]] Sampler2D samplerNormalMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input, uniform float4x4 modelMat) -{ - VSOutput output; - output.Normal = input.Normal; - output.UV = input.UV; - output.Tangent = input.Tangent; - - float4x4 modelView = mul(ubo.view, modelMat); - - output.Pos = mul(ubo.projection, mul(modelView, float4(input.Pos.xyz, 1.0))); - - output.Normal = mul((float3x3)modelMat, input.Normal); - float4 pos = mul(modelMat, float4(input.Pos, 1.0)); - output.LightVec = ubo.lightPos.xyz - pos.xyz; - output.ViewVec = ubo.viewPos.xyz - pos.xyz; - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input, uniform float4x4 modelMat, uniform uint alphaMask, uniform float alphaMaskCutoff) -{ - float4 color = samplerColorMap.Sample(input.UV); - - if (alphaMask == 1) { - if (color.a < alphaMaskCutoff) { - discard; - } - } - - float3 N = normalize(input.Normal); - float3 T = normalize(input.Tangent.xyz); - float3 B = cross(input.Normal, input.Tangent.xyz) * input.Tangent.w; - float3x3 TBN = float3x3(T, B, N); - N = mul(normalize(samplerNormalMap.Sample(input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); - - const float ambient = 0.1; - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 diffuse = max(dot(N, L), ambient).rrr; - float3 specular = pow(max(dot(R, V), 0.0), 32.0); - return float4(diffuse * color.rgb + specular, color.a); -} \ No newline at end of file diff --git a/shaders/slang/vertexattributes/scene.vert.spv b/shaders/slang/vertexattributes/scene.vert.spv deleted file mode 100644 index 4ed62fbb..00000000 Binary files a/shaders/slang/vertexattributes/scene.vert.spv and /dev/null differ diff --git a/shaders/slang/viewportarray/multiview.geom.spv b/shaders/slang/viewportarray/multiview.geom.spv deleted file mode 100644 index b980b0f6..00000000 Binary files a/shaders/slang/viewportarray/multiview.geom.spv and /dev/null differ diff --git a/shaders/slang/viewportarray/scene.frag.spv b/shaders/slang/viewportarray/scene.frag.spv deleted file mode 100644 index 6cbde14f..00000000 Binary files a/shaders/slang/viewportarray/scene.frag.spv and /dev/null differ diff --git a/shaders/slang/viewportarray/scene.slang b/shaders/slang/viewportarray/scene.slang deleted file mode 100644 index e6b6eb7e..00000000 --- a/shaders/slang/viewportarray/scene.slang +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; - float3 Normal; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 Normal; - float3 Color; -}; - -struct GSOutput -{ - float4 Pos : SV_POSITION; - uint ViewportIndex : SV_ViewportArrayIndex; - uint PrimitiveID : SV_PrimitiveID; - float3 Normal; - float3 Color; - float3 ViewVec; - float3 LightVec; -} - -struct UBO -{ - float4x4 projection[2]; - float4x4 modelview[2]; - float4 lightPos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.Color = input.Color; - output.Normal = input.Normal; - output.Pos = float4(input.Pos.xyz, 1.0); - return output; -} - -[shader("geometry")] -[maxvertexcount(3)] -[instance(2)] -void geometryMain(triangle VSOutput input[3], inout TriangleStream outStream, uint InvocationID: SV_GSInstanceID, uint PrimitiveID: SV_PrimitiveID) -{ - for (int i = 0; i < 3; i++) - { - GSOutput output; - output.Normal = mul((float3x3)ubo.modelview[InvocationID], input[i].Normal); - output.Color = input[i].Color; - - float4 pos = input[i].Pos; - float4 worldPos = mul(ubo.modelview[InvocationID], pos); - - float3 lPos = mul(ubo.modelview[InvocationID], ubo.lightPos).xyz; - output.LightVec = lPos - worldPos.xyz; - output.ViewVec = -worldPos.xyz; - - output.Pos = mul(ubo.projection[InvocationID], worldPos); - - // Set the viewport index that the vertex will be emitted to - output.ViewportIndex = InvocationID; - output.PrimitiveID = PrimitiveID; - outStream.Append(output); - } - - outStream.RestartStrip(); -} - -[shader("fragment")] -float4 fragmentMain(GSOutput input) -{ - float3 N = normalize(input.Normal); - float3 L = normalize(input.LightVec); - float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); - float3 ambient = float3(0.1, 0.1, 0.1); - float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); - float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); - return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); -} \ No newline at end of file diff --git a/shaders/slang/viewportarray/scene.vert.spv b/shaders/slang/viewportarray/scene.vert.spv deleted file mode 100644 index 0b22093f..00000000 Binary files a/shaders/slang/viewportarray/scene.vert.spv and /dev/null differ diff --git a/shaders/slang/vulkanscene/logo.frag.spv b/shaders/slang/vulkanscene/logo.frag.spv deleted file mode 100644 index ea6e69d8..00000000 Binary files a/shaders/slang/vulkanscene/logo.frag.spv and /dev/null differ diff --git a/shaders/slang/vulkanscene/logo.slang b/shaders/slang/vulkanscene/logo.slang deleted file mode 100644 index 95974e79..00000000 --- a/shaders/slang/vulkanscene/logo.slang +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Normal; - float2 TexCoord; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float3 Normal; - float3 Color; - float3 EyePos; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 normal; - float4x4 view; - float3 lightpos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - float4x4 modelView = mul(ubo.view, ubo.model); - float4 pos = mul(modelView, input.Pos); - output.UV = input.TexCoord.xy; - output.Normal = normalize(mul((float3x3)ubo.normal, input.Normal)); - output.Color = input.Color; - output.Pos = mul(ubo.projection, pos); - output.EyePos = mul(modelView, pos).xyz; - float4 lightPos = mul(modelView, float4(1.0, 2.0, 0.0, 1.0)); - output.LightVec = normalize(lightPos.xyz - output.EyePos); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - float4 diff = float4(input.Color, 1.0) * max(dot(input.Normal, input.LightVec), 0.0); - float shininess = 0.0; - float4 spec = float4(1.0, 1.0, 1.0, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 2.5) * shininess; - return float4((diff + spec).rgb, 1); -} \ No newline at end of file diff --git a/shaders/slang/vulkanscene/logo.vert.spv b/shaders/slang/vulkanscene/logo.vert.spv deleted file mode 100644 index c804643c..00000000 Binary files a/shaders/slang/vulkanscene/logo.vert.spv and /dev/null differ diff --git a/shaders/slang/vulkanscene/mesh.frag.spv b/shaders/slang/vulkanscene/mesh.frag.spv deleted file mode 100644 index acd220e8..00000000 Binary files a/shaders/slang/vulkanscene/mesh.frag.spv and /dev/null differ diff --git a/shaders/slang/vulkanscene/mesh.slang b/shaders/slang/vulkanscene/mesh.slang deleted file mode 100644 index 61c80c11..00000000 --- a/shaders/slang/vulkanscene/mesh.slang +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float4 Pos; - float3 Normal; - float2 TexCoord; - float3 Color; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float2 UV; - float3 Normal; - float3 Color; - float3 EyePos; - float3 LightVec; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 normal; - float4x4 view; - float3 lightpos; -}; -ConstantBuffer ubo; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - output.UV = input.TexCoord.xy; - output.Normal = normalize(mul((float3x3)ubo.normal, input.Normal)); - output.Color = input.Color; - float4x4 modelView = mul(ubo.view, ubo.model); - float4 pos = mul(modelView, input.Pos); - output.Pos = mul(ubo.projection, pos); - output.EyePos = mul(modelView, pos).xyz; - float4 lightPos = mul(modelView, float4(ubo.lightpos, 1.0)); - output.LightVec = normalize(lightPos.xyz - output.EyePos); - return output; -} - -float specpart(float3 L, float3 N, float3 H) -{ - if (dot(N, L) > 0.0) - { - return pow(clamp(dot(H, N), 0.0, 1.0), 64.0); - } - return 0.0; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - float3 Eye = normalize(-input.EyePos); - float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); - - float3 halfVec = normalize(input.LightVec + input.EyePos); - float diff = clamp(dot(input.LightVec, input.Normal), 0.0, 1.0); - float spec = specpart(input.LightVec, input.Normal, halfVec); - float intensity = 0.1 + diff + spec; - - float4 IAmbient = float4(0.2, 0.2, 0.2, 1.0); - float4 IDiffuse = float4(0.5, 0.5, 0.5, 0.5) * max(dot(input.Normal, input.LightVec), 0.0); - float shininess = 0.75; - float4 ISpecular = float4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 2.0) * shininess; - - float4 outFragColor = float4((IAmbient + IDiffuse) * float4(input.Color, 1.0) + ISpecular); - - // Some manual saturation - if (intensity > 0.95) - outFragColor *= 2.25; - if (intensity < 0.15) - outFragColor = float4(0.1, 0.1, 0.1, 0.1); - - return outFragColor; -} \ No newline at end of file diff --git a/shaders/slang/vulkanscene/mesh.vert.spv b/shaders/slang/vulkanscene/mesh.vert.spv deleted file mode 100644 index 962fd3c4..00000000 Binary files a/shaders/slang/vulkanscene/mesh.vert.spv and /dev/null differ diff --git a/shaders/slang/vulkanscene/skybox.frag.spv b/shaders/slang/vulkanscene/skybox.frag.spv deleted file mode 100644 index 71e6a035..00000000 Binary files a/shaders/slang/vulkanscene/skybox.frag.spv and /dev/null differ diff --git a/shaders/slang/vulkanscene/skybox.slang b/shaders/slang/vulkanscene/skybox.slang deleted file mode 100644 index 98d38560..00000000 --- a/shaders/slang/vulkanscene/skybox.slang +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2025, Sascha Willems - * - * SPDX-License-Identifier: MIT - * - */ - -struct VSInput -{ - float3 Pos; -}; - -struct VSOutput -{ - float4 Pos : SV_POSITION; - float3 UVW; -}; - -struct UBO -{ - float4x4 projection; - float4x4 model; - float4x4 normal; - float4x4 view; -}; -ConstantBuffer ubo; -SamplerCube samplerCubeMap; - -[shader("vertex")] -VSOutput vertexMain(VSInput input) -{ - VSOutput output; - // Remove translation from view matrix - float4x4 viewMat = ubo.view; - viewMat[0][3] = 0.0; - viewMat[1][3] = 0.0; - viewMat[2][3] = 0.0; - output.UVW = input.Pos; - output.Pos = mul(ubo.projection, mul(viewMat, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); - return output; -} - -[shader("fragment")] -float4 fragmentMain(VSOutput input) -{ - return samplerCubeMap.Sample(input.UVW); -} \ No newline at end of file diff --git a/shaders/slang/vulkanscene/skybox.vert.spv b/shaders/slang/vulkanscene/skybox.vert.spv deleted file mode 100644 index 427b41e3..00000000 Binary files a/shaders/slang/vulkanscene/skybox.vert.spv and /dev/null differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..f68da6fc --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,87 @@ +# Procedural 3D Engine +# Copyright (c) 2025 Your Project +# Licensed under the MIT License + +cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR) + +set(TARGET_NAME "ProceduralEngine3D") + +# Collect source files +file(GLOB_RECURSE SOURCES + "*.cpp" + "*.h" +) + +# Include ImGui source files +file(GLOB IMGUI_SOURCES + "../external/imgui/*.cpp" +) + +# Collect shader files +set(SHADER_DIR_GLSL "../shaders/glsl/imgui") +file(GLOB SHADERS_GLSL + "${SHADER_DIR_GLSL}/*.vert" + "${SHADER_DIR_GLSL}/*.frag" + "${SHADER_DIR_GLSL}/*.comp" + "${SHADER_DIR_GLSL}/*.spv" +) + +source_group("Shaders" FILES ${SHADERS_GLSL}) +source_group("ImGui" FILES ${IMGUI_SOURCES}) +source_group("Core" FILES core/*.cpp core/*.h) +source_group("Scene" FILES scene/*.cpp scene/*.h) +source_group("UI" FILES ui/*.cpp ui/*.h) +source_group("Rendering" FILES rendering/*.cpp rendering/*.h) + +# Create executable (console application) +if(WIN32) + add_executable(${TARGET_NAME} + ${SOURCES} + ${IMGUI_SOURCES} + ${SHADERS_GLSL} + ) + target_link_libraries(${TARGET_NAME} + base + ${Vulkan_LIBRARY} + ${WINLIBS} + ) + # Use Windows subsystem for Vulkan windowed application + set_target_properties(${TARGET_NAME} PROPERTIES + LINK_FLAGS "/SUBSYSTEM:WINDOWS" + ) +else() + add_executable(${TARGET_NAME} + ${SOURCES} + ${IMGUI_SOURCES} + ${SHADERS_GLSL} + ) + target_link_libraries(${TARGET_NAME} base) +endif() + +# Include directories +target_include_directories(${TARGET_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ../base + ../base/device + ../base/memory + ../base/core + ../base/foundation + ../external + ../external/glm + ../external/imgui + ../external/tinygltf + ../external/ktx/include + ../external/ktx/other_include +) + +# Set output directory +file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) +set_target_properties(${TARGET_NAME} PROPERTIES + VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin +) + +# Install target +if(RESOURCE_INSTALL_DIR) + install(TARGETS ${TARGET_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() \ No newline at end of file diff --git a/src/core/Application.cpp b/src/core/Application.cpp new file mode 100644 index 00000000..6f70ac8a --- /dev/null +++ b/src/core/Application.cpp @@ -0,0 +1,669 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#include "Application.h" +#include "../ui/UIManager.h" +#include "../ui/UISettings.h" +#include +#include + +// For Windows Alt key detection +#ifdef _WIN32 +#include +#endif + +// Global UI settings instance +UISettings uiSettings; + +Application::Application() : VulkanExampleBase() +{ + title = "ProceduralEngine - Vulkan 3D Viewport"; + + // Configure standard camera for 3D viewport + camera.type = Camera::CameraType::lookat; + camera.setPosition(glm::vec3(0.0f, 0.5f, -8.0f)); // Much closer to origin for immediate object visibility + camera.setRotation(glm::vec3(-15.0f, 0.0f, 0.0f)); // Look slightly down at origin + camera.setPerspective(45.0f, (float)width / (float)height, 0.1f, 256.0f); + camera.setMovementSpeed(2.5f); // Standard movement speed + camera.setRotationSpeed(0.25f); // Standard rotation speed + + //SRS - Enable VK_KHR_get_physical_device_properties2 to retrieve device driver information for display + enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + + // Enable dynamic rendering extensions + enabledDeviceExtensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME); + + // Enable dynamic rendering features + enabledDynamicRenderingFeaturesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR; + enabledDynamicRenderingFeaturesKHR.dynamicRendering = VK_TRUE; + + deviceCreatepNextChain = &enabledDynamicRenderingFeaturesKHR; + + // Don't use the ImGui overlay of the base framework in this sample + settings.overlay = false; + + // Initialize UI system + uiManager = nullptr; + + std::cout << "Application constructor completed" << std::endl; +} + +Application::~Application() +{ + vkDestroyPipeline(device, pipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + + vkDestroyPipeline(device, proceduralPipeline, nullptr); + vkDestroyPipelineLayout(device, proceduralPipelineLayout, nullptr); + vkDestroyDescriptorSetLayout(device, proceduralDescriptorSetLayout, nullptr); + + uniformBufferVS.destroy(); + + delete uiManager; + + std::cout << "Application destructor completed" << std::endl; +} + + +void Application::setupRenderPass() +{ + // With VK_KHR_dynamic_rendering we no longer need a render pass, so skip the sample base render pass setup + renderPass = VK_NULL_HANDLE; +} + +void Application::setupFrameBuffer() +{ + // With VK_KHR_dynamic_rendering we no longer need a frame buffer, so skip the sample base framebuffer setup +} + +void Application::renderProceduralShapes(VkCommandBuffer commandBuffer) +{ + // Render procedural shapes using persistent buffers + static int frameCount = 0; + static int lastReportedObjectCount = -1; + frameCount++; + + // Report object count changes + int currentObjectCount = sceneManager.getObjectCount(); + if (currentObjectCount != lastReportedObjectCount) { + std::cout << "Renderer: Scene has " << currentObjectCount << " objects" << std::endl; + lastReportedObjectCount = currentObjectCount; + } + + int visibleObjectsRendered = 0; + + for (auto& obj : sceneManager.getObjects()) { + // Debug visibility and buffer status + if (obj.type == "Procedural") { + if (!obj.visible) { + continue; // Skip invisible objects silently + } + if (obj.indices.empty()) { + if (frameCount % 120 == 0) { // Report every 2 seconds at 60fps + std::cout << "Renderer: Object '" << obj.name << "' has no geometry data" << std::endl; + } + continue; + } + if (!obj.vulkanBuffers.buffersCreated) { + if (frameCount % 120 == 0) { // Report every 2 seconds at 60fps + std::cout << "Renderer: Object '" << obj.name << "' has no Vulkan buffers" << std::endl; + } + continue; + } + } + + if (obj.type == "Procedural" && obj.visible && !obj.indices.empty() && obj.vulkanBuffers.buffersCreated) { + // Calculate model matrix for this object + glm::mat4 model = glm::mat4(1.0f); + model = glm::translate(model, obj.position); + model = glm::rotate(model, glm::radians(obj.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); + model = glm::rotate(model, glm::radians(obj.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); + model = glm::rotate(model, glm::radians(obj.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); + model = glm::scale(model, obj.scale); + + // Update uniform buffer with object's model matrix while preserving camera matrices + UBOVS tempUBO; + tempUBO.projection = camera.matrices.perspective; // Use standard camera projection + tempUBO.model = camera.matrices.view * model; // Combine view and model matrices + tempUBO.lightPos = uboVS.lightPos; // Preserve light position + + VK_CHECK_RESULT(uniformBufferVS.map()); + memcpy(uniformBufferVS.mapped, &tempUBO, sizeof(tempUBO)); + uniformBufferVS.unmap(); + + // Validate buffers before binding + if (obj.vulkanBuffers.vertexBuffer.buffer == VK_NULL_HANDLE || obj.vulkanBuffers.indexBuffer.buffer == VK_NULL_HANDLE) { + std::cout << "Warning: Invalid buffer handles for " << obj.name << std::endl; + continue; + } + + // Bind the vertex and index buffers for this object + VkBuffer vertexBuffers[] = { obj.vulkanBuffers.vertexBuffer.buffer }; + VkDeviceSize offsets[] = { 0 }; + vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); + vkCmdBindIndexBuffer(commandBuffer, obj.vulkanBuffers.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); + + // Draw the object + vkCmdDrawIndexed(commandBuffer, static_cast(obj.indices.size()), 1, 0, 0, 0); + visibleObjectsRendered++; + + // Debug output for rendering objects + if (frameCount % 60 == 0) { // Every second at 60fps + std::cout << "Rendering " << obj.name << " at (" << obj.position.x << ", " << obj.position.y << ", " << obj.position.z << ") with " << obj.indices.size() << " indices" << std::endl; + } + } + } + + // Debug output for frame rendering summary + if (frameCount % 60 == 0 && visibleObjectsRendered > 0) { + std::cout << "Frame " << frameCount << ": Rendered " << visibleObjectsRendered << " objects" << std::endl; + } +} + +void Application::buildCommandBuffers() +{ + VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); + + // UIManager handles the frame preparation in render() method now + + for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) + { + VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); + + // Dynamic rendering requires manual image layout transitions + // Prepare color attachment for rendering + vks::tools::insertImageMemoryBarrier( + drawCmdBuffers[i], + swapChain.images[i], + 0, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); + + // Prepare depth attachment for rendering + vks::tools::insertImageMemoryBarrier( + drawCmdBuffers[i], + depthStencil.image, + 0, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VkImageSubresourceRange{ VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1 }); + + // Set up rendering attachments for dynamic rendering + VkRenderingAttachmentInfoKHR colorAttachment{}; + colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; + colorAttachment.imageView = swapChain.imageViews[i]; + colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.clearValue.color = { 0.2f, 0.2f, 0.2f, 1.0f }; + + VkRenderingAttachmentInfoKHR depthStencilAttachment{}; + depthStencilAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; + depthStencilAttachment.imageView = depthStencil.view; + depthStencilAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depthStencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depthStencilAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + depthStencilAttachment.clearValue.depthStencil = { 1.0f, 0 }; + + VkRenderingInfoKHR renderingInfo{}; + renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR; + renderingInfo.renderArea = { 0, 0, width, height }; + renderingInfo.layerCount = 1; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &colorAttachment; + renderingInfo.pDepthAttachment = &depthStencilAttachment; + renderingInfo.pStencilAttachment = &depthStencilAttachment; + + // Begin dynamic rendering + vkCmdBeginRenderingKHR(drawCmdBuffers[i], &renderingInfo); + + VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); + vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); + + VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); + vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); + + // Render vkglTF models with original pipeline + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + + if (uiSettings.displayBackground) { + models.background.draw(drawCmdBuffers[i]); + } + + if (uiSettings.displayModels) { + models.models.draw(drawCmdBuffers[i]); + } + + // Switch to procedural pipeline for procedural shapes + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, proceduralPipelineLayout, 0, 1, &proceduralDescriptorSet, 0, nullptr); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, proceduralPipeline); + + // Render procedural shapes + renderProceduralShapes(drawCmdBuffers[i]); + + // Render UIManager UI + if (ui.visible && uiManager) { + uiManager->drawFrame(drawCmdBuffers[i]); + } + + // End dynamic rendering + vkCmdEndRenderingKHR(drawCmdBuffers[i]); + + // Prepare image for presentation + vks::tools::insertImageMemoryBarrier( + drawCmdBuffers[i], + swapChain.images[i], + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + 0, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); + + VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); + } + + std::cout << "buildCommandBuffers() completed successfully" << std::endl; +} + +void Application::updateUniformBuffers() +{ + // Update standard camera + camera.update(frameTimer); + + // Debug camera position and matrices (only every 120 frames to avoid spam) + static int debugFrameCount = 0; + debugFrameCount++; + if (debugFrameCount % 120 == 0) { + std::cout << "Camera Debug - Position: (" << camera.position.x << ", " << camera.position.y << ", " << camera.position.z << ")" << std::endl; + std::cout << "Camera Debug - Rotation: (" << camera.rotation.x << ", " << camera.rotation.y << ", " << camera.rotation.z << ")" << std::endl; + } + + // Vertex shader - use standard camera matrices + uboVS.projection = camera.matrices.perspective; + uboVS.model = camera.matrices.view * glm::mat4(1.0f); + + // Light source + if (uiSettings.animateLight) { + uiSettings.lightTimer += frameTimer * uiSettings.lightSpeed; + uboVS.lightPos.x = sin(glm::radians(uiSettings.lightTimer * 360.0f)) * 15.0f; + uboVS.lightPos.z = cos(glm::radians(uiSettings.lightTimer * 360.0f)) * 15.0f; + }; + + VK_CHECK_RESULT(uniformBufferVS.map()); + memcpy(uniformBufferVS.mapped, &uboVS, sizeof(uboVS)); + uniformBufferVS.unmap(); +} + +void Application::prepareImGui() +{ + // UIManager will handle all ImGui initialization, no need for separate ImGUI class + std::cout << "prepareImGui() - UIManager will handle ImGui initialization" << std::endl; +} + +void Application::prepareUniformBuffers() +{ + // Vertex shader uniform buffer block + VK_CHECK_RESULT(vulkanDevice->createBuffer( + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &uniformBufferVS, + sizeof(uboVS), + &uboVS)); + + updateUniformBuffers(); + + std::cout << "prepareUniformBuffers() completed successfully" << std::endl; +} + +void Application::loadAssets() +{ + std::cout << "Loading assets (placeholder implementation)" << std::endl; +} + +void Application::prepare() +{ + VulkanExampleBase::prepare(); + + // Get dynamic rendering function pointers + vkCmdBeginRenderingKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBeginRenderingKHR")); + vkCmdEndRenderingKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdEndRenderingKHR")); + + // Validate function pointers + if (!vkCmdBeginRenderingKHR || !vkCmdEndRenderingKHR) { + std::cout << "ERROR: Failed to load dynamic rendering function pointers" << std::endl; + exit(1); + } + + // Initialize scene manager with device pointer + sceneManager.setVulkanDevice(vulkanDevice); + + loadAssets(); + prepareUniformBuffers(); + setupLayoutsAndDescriptors(); + preparePipelines(); + setupProceduralDescriptorSet(); + prepareImGui(); + initializeUI(); + buildCommandBuffers(); + prepared = true; + + std::cout << "Application prepared successfully with full Vulkan pipeline" << std::endl; +} + +void Application::render() +{ + std::cout << "Application::render() called" << std::endl; + + if (!prepared) + return; + + std::cout << "Calling updateUniformBuffers()" << std::endl; + updateUniformBuffers(); + + std::cout << "Updating UIManager" << std::endl; + // Update UIManager instead of stub imGui + if (uiManager) { + std::cout << "Setting up ImGui IO before newFrame()" << std::endl; + // Update ImGui IO BEFORE calling newFrame() - this is critical for input processing + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2((float)width, (float)height); + io.DeltaTime = frameTimer; + + // Feed mouse state to ImGui (following Sascha's imgui example pattern) + // This MUST be done before NewFrame() for ImGui to process input correctly + io.MousePos = ImVec2(mouseState.position.x, mouseState.position.y); + io.MouseDown[0] = mouseState.buttons.left && ui.visible; + io.MouseDown[1] = mouseState.buttons.right && ui.visible; + io.MouseDown[2] = mouseState.buttons.middle && ui.visible; + + // Debug mouse state (only print when mouse buttons are pressed) + if (mouseState.buttons.left || mouseState.buttons.right || mouseState.buttons.middle) { + std::cout << "DEBUG Mouse: pos(" << mouseState.position.x << "," << mouseState.position.y + << ") left:" << mouseState.buttons.left << " right:" << mouseState.buttons.right + << " middle:" << mouseState.buttons.middle << " ui.visible:" << ui.visible << std::endl; + } + + std::cout << "Calling uiManager->newFrame()" << std::endl; + uiManager->newFrame(this, frameCounter == 0); + + std::cout << "Calling uiManager->updateBuffers()" << std::endl; + uiManager->updateBuffers(); + } + + std::cout << "Calling draw()" << std::endl; + draw(); +} + +void Application::draw() +{ + VulkanExampleBase::prepareFrame(); + + // Check if we need to create buffers for new objects + bool needsCommandBufferRebuild = false; + for (auto& obj : sceneManager.getObjects()) { + if (obj.type == "Procedural" && !obj.vulkanBuffers.buffersCreated && !obj.vertices.empty() && !obj.indices.empty()) { + // Wait for GPU to finish current operations before creating new buffers + vkDeviceWaitIdle(device); + sceneManager.createBuffersForObject(const_cast(obj), vulkanDevice); + needsCommandBufferRebuild = true; + } + } + + // If new objects were added, ensure proper synchronization + if (needsCommandBufferRebuild) { + vkDeviceWaitIdle(device); + } + + buildCommandBuffers(); + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; + VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + VulkanExampleBase::submitFrame(); +} + +void Application::setupLayoutsAndDescriptors() +{ + // descriptor pool (increased to handle procedural pipeline too) + std::vector poolSizes = { + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) + }; + VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 4); + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); + + // Set layout + std::vector setLayoutBindings = { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), + }; + VkDescriptorSetLayoutCreateInfo descriptorLayout = + vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); + + // Pipeline layout + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + + // Descriptor set + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); + std::vector writeDescriptorSets = { + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferVS.descriptor), + }; + vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); + + std::cout << "setupLayoutsAndDescriptors() completed successfully" << std::endl; +} + +void Application::setupProceduralDescriptorSet() +{ + // Allocate procedural descriptor set + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &proceduralDescriptorSetLayout, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &proceduralDescriptorSet)); + std::vector writeDescriptorSets = { + vks::initializers::writeDescriptorSet(proceduralDescriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferVS.descriptor), + }; + vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); + + std::cout << "setupProceduralDescriptorSet() completed successfully" << std::endl; +} + +void Application::preparePipelines() +{ + // Rendering + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); + VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); + VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); + + std::array shaderStages; + + // Create pipeline without render pass for dynamic rendering + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(); + pipelineCI.layout = pipelineLayout; + pipelineCI.pInputAssemblyState = &inputAssemblyState; + pipelineCI.pRasterizationState = &rasterizationState; + pipelineCI.pColorBlendState = &colorBlendState; + pipelineCI.pMultisampleState = &multisampleState; + pipelineCI.pViewportState = &viewportState; + pipelineCI.pDepthStencilState = &depthStencilState; + pipelineCI.pDynamicState = &dynamicState; + pipelineCI.stageCount = static_cast(shaderStages.size()); + pipelineCI.pStages = shaderStages.data(); + pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color });; + + // Dynamic rendering create info to define color, depth and stencil attachments at pipeline create time + VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo{}; + pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; + pipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipelineRenderingCreateInfo.pColorAttachmentFormats = &swapChain.colorFormat; + pipelineRenderingCreateInfo.depthAttachmentFormat = depthFormat; + pipelineRenderingCreateInfo.stencilAttachmentFormat = depthFormat; + // Chain into the pipeline create info + pipelineCI.pNext = &pipelineRenderingCreateInfo; + + shaderStages[0] = loadShader(getShadersPath() + "imgui/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getShadersPath() + "imgui/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); + + // Create procedural shapes pipeline + prepareProceduralPipeline(); + + std::cout << "preparePipelines() completed successfully" << std::endl; +} + +void Application::prepareProceduralPipeline() +{ + // Descriptor set layout for procedural shapes (uniform buffer only) + VkDescriptorSetLayoutBinding layoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); + VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(&layoutBinding, 1); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &proceduralDescriptorSetLayout)); + + // Pipeline layout + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&proceduralDescriptorSetLayout, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &proceduralPipelineLayout)); + + // Pipeline + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); + VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); + VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); + + // Vertex input for procedural shapes + VkVertexInputBindingDescription vertexInputBinding = vks::initializers::vertexInputBindingDescription(0, sizeof(ProceduralVertex), VK_VERTEX_INPUT_RATE_VERTEX); + std::vector vertexInputAttributes = { + vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Position + vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Normal + vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 6), // Color + }; + VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); + vertexInputState.vertexBindingDescriptionCount = 1; + vertexInputState.pVertexBindingDescriptions = &vertexInputBinding; + vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); + vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); + + std::array shaderStages; + + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(); + pipelineCI.layout = proceduralPipelineLayout; + pipelineCI.pInputAssemblyState = &inputAssemblyState; + pipelineCI.pRasterizationState = &rasterizationState; + pipelineCI.pColorBlendState = &colorBlendState; + pipelineCI.pMultisampleState = &multisampleState; + pipelineCI.pViewportState = &viewportState; + pipelineCI.pDepthStencilState = &depthStencilState; + pipelineCI.pDynamicState = &dynamicState; + pipelineCI.pVertexInputState = &vertexInputState; + pipelineCI.stageCount = static_cast(shaderStages.size()); + pipelineCI.pStages = shaderStages.data(); + + // Dynamic rendering create info + VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo{}; + pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; + pipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipelineRenderingCreateInfo.pColorAttachmentFormats = &swapChain.colorFormat; + pipelineRenderingCreateInfo.depthAttachmentFormat = depthFormat; + pipelineRenderingCreateInfo.stencilAttachmentFormat = depthFormat; + pipelineCI.pNext = &pipelineRenderingCreateInfo; + + shaderStages[0] = loadShader(getShadersPath() + "imgui/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getShadersPath() + "imgui/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &proceduralPipeline)); + + std::cout << "prepareProceduralPipeline() completed successfully" << std::endl; +} + +void Application::initializeUI() +{ + uiManager = new UIManager(this); + + std::cout << "Setting UISettings pointer: " << &uiSettings << std::endl; + uiManager->setUISettings(&uiSettings); + + std::cout << "Setting SceneManager pointer: " << &sceneManager << std::endl; + uiManager->setSceneManager(&sceneManager); + + uiManager->init(1920.0f, 1080.0f); // Default resolution, will be updated when proper Vulkan integration is complete + + // Set the Vulkan device for UIManager and initialize full resources + uiManager->setDevice(vulkanDevice); + uiManager->initResources(VK_NULL_HANDLE, queue, getShadersPath(), swapChain.colorFormat, depthFormat); + + std::cout << "UI system initialized with UIManager and full Vulkan resources" << std::endl; +} + + +void Application::keyPressed(uint32_t keyCode) +{ + ImGuiIO& io = ImGui::GetIO(); + + // Forward key input to ImGui if it wants keyboard input + if (io.WantCaptureKeyboard) { + // ImGui handles this key, don't process application shortcuts + return; + } + + // F key: Focus on selected object using Sascha's infrastructure + if (keyCode == KEY_F) { + if (sceneManager.getSelectedIndex() >= 0) { + const SceneObject* selectedObject = sceneManager.getSelectedObject(); + if (selectedObject) { + // Get object bounding info + glm::vec3 objectCenter = selectedObject->getBoundingBoxCenter(); + float objectRadius = selectedObject->getBoundingRadius(); + + // Use the new proper focus system + camera.focusOnObject(objectCenter, objectRadius); + + std::cout << "F key focus: " << selectedObject->name + << " at (" << objectCenter.x << "," << objectCenter.y << "," << objectCenter.z << ")" << std::endl; + } + } else { + std::cout << "F key: No object selected" << std::endl; + } + } + + // Call base implementation for other keys + VulkanExampleBase::keyPressed(keyCode); +} + +void Application::mouseMoved(double x, double y, bool &handled) +{ + // Check if ImGui wants the mouse (hovering over UI elements) + ImGuiIO& io = ImGui::GetIO(); + if (io.WantCaptureMouse && ui.visible) { + handled = true; // Block camera controls when over UI + return; + } + handled = false; // Allow camera controls when not over UI +} + diff --git a/src/core/Application.h b/src/core/Application.h new file mode 100644 index 00000000..561131f8 --- /dev/null +++ b/src/core/Application.h @@ -0,0 +1,98 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#pragma once + +#include "foundation/vulkanexamplebase.h" +#include "VulkanglTFModel.h" +#include "keycodes.hpp" +#include "../scene/SceneManager.h" +#include "../scene/ProceduralGeometry.h" +#include +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +// Forward declarations +class UIManager; +struct UISettings; + +class Application : public VulkanExampleBase +{ +public: + // Dynamic rendering function pointers + PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR{ VK_NULL_HANDLE }; + PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR{ VK_NULL_HANDLE }; + + VkPhysicalDeviceDynamicRenderingFeaturesKHR enabledDynamicRenderingFeaturesKHR{}; + + UIManager *uiManager = nullptr; + + struct Models { + vkglTF::Model models; + vkglTF::Model logos; + vkglTF::Model background; + } models; + + vks::Buffer uniformBufferVS; + + struct UBOVS { + glm::mat4 projection; + glm::mat4 model; + glm::vec4 lightPos; + } uboVS; + + VkPipelineLayout pipelineLayout; + VkPipeline pipeline; + VkDescriptorSetLayout descriptorSetLayout; + VkDescriptorSet descriptorSet; + + // Procedural shapes pipeline + VkPipelineLayout proceduralPipelineLayout; + VkPipeline proceduralPipeline; + VkDescriptorSetLayout proceduralDescriptorSetLayout; + VkDescriptorSet proceduralDescriptorSet; + + // Using inherited camera from VulkanExampleBase (no OrbitCamera needed) + + // Scene management + SceneManager sceneManager; + + Application(); + ~Application(); + + // Vulkan setup methods (virtual overrides) + virtual void setupRenderPass() override; + virtual void setupFrameBuffer() override; + virtual void buildCommandBuffers() override; + virtual void prepare() override; + virtual void render() override; + + // Input handling (virtual overrides) + virtual void keyPressed(uint32_t keyCode) override; + virtual void mouseMoved(double x, double y, bool &handled) override; + + // Rendering methods + void draw(); + void renderProceduralShapes(VkCommandBuffer commandBuffer); + void updateUniformBuffers(); + void prepareUniformBuffers(); + void preparePipelines(); + void prepareProceduralPipeline(); + void setupLayoutsAndDescriptors(); + void setupProceduralDescriptorSet(); + void prepareImGui(); + +private: + void loadAssets(); + void setupDynamicRendering(); + void initializeUI(); +}; \ No newline at end of file diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp new file mode 100644 index 00000000..09c24e62 --- /dev/null +++ b/src/core/Camera.cpp @@ -0,0 +1,238 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#include "Camera.h" +#include +#include + +OrbitCamera::OrbitCamera(glm::vec3 initialPosition, glm::vec3 focusPoint) { + m_currentFocusPoint = focusPoint; + m_targetFocusPoint = focusPoint; + + // Calculate initial spherical coordinates from position + glm::vec3 offset = initialPosition - focusPoint; + m_currentDistance = glm::length(offset); + m_targetDistance = m_currentDistance; + + // Calculate initial angles + CartesianToSpherical(initialPosition, focusPoint, m_currentDistance, m_currentAzimuth, m_currentElevation); + m_targetAzimuth = m_currentAzimuth; + m_targetElevation = m_currentElevation; + + m_currentPosition = initialPosition; + + // Set default parameters + m_fov = 45.0f; + m_smoothingFactor = 0.1f; + m_orbitSensitivity = 0.5f; + m_panSensitivity = 0.00003f; + m_zoomSensitivity = 0.1f; + + // Set constraints + m_minDistance = 0.5f; + m_maxDistance = 100.0f; + m_minElevation = -89.0f; + m_maxElevation = 89.0f; + + m_viewMatrixDirty = true; +} + +void OrbitCamera::Orbit(float deltaAzimuth, float deltaElevation, float deltaTime) { + // Apply input to target angles (convert degrees to radians) + m_targetAzimuth += glm::radians(deltaAzimuth * m_orbitSensitivity); + m_targetElevation += glm::radians(deltaElevation * m_orbitSensitivity); + ClampConstraints(); +} + +void OrbitCamera::Pan(float deltaX, float deltaY, float deltaTime) { + // Get camera's right and up vectors for screen-space panning + glm::mat4 viewMatrix = GetViewMatrix(); + glm::vec3 right = glm::vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]); + glm::vec3 up = glm::vec3(viewMatrix[0][1], viewMatrix[1][1], viewMatrix[2][1]); + + // Scale pan speed by distance to focus point for consistent behavior + float panScale = m_currentDistance * m_panSensitivity; + + // Move focus point + glm::vec3 panOffset = right * deltaX * panScale + up * deltaY * panScale; + m_targetFocusPoint += panOffset; +} + +void OrbitCamera::Zoom(float deltaDistance, float deltaTime) { + // Apply zoom with distance-based scaling for consistent behavior + m_targetDistance += deltaDistance * m_zoomSensitivity * m_currentDistance * 0.1f; + m_targetDistance = glm::clamp(m_targetDistance, m_minDistance, m_maxDistance); +} + +void OrbitCamera::ZoomImmediate(float deltaDistance, float deltaTime) { + // Apply zoom with immediate response (no smoothing/velocity) + float zoomAmount = deltaDistance * m_zoomSensitivity * m_currentDistance * 0.1f; + + // Set both target AND current immediately (no smoothing) + m_targetDistance += zoomAmount; + m_targetDistance = glm::clamp(m_targetDistance, m_minDistance, m_maxDistance); + m_currentDistance = m_targetDistance; + m_viewMatrixDirty = true; +} + +void OrbitCamera::PanImmediate(float deltaX, float deltaY, float deltaTime) { + // Get camera's right and up vectors for screen-space panning + glm::mat4 viewMatrix = GetViewMatrix(); + glm::vec3 right = glm::vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]); + glm::vec3 up = glm::vec3(viewMatrix[0][1], viewMatrix[1][1], viewMatrix[2][1]); + + // Scale pan speed by distance to focus point for consistent behavior + float panScale = m_currentDistance * m_panSensitivity; + + // Calculate pan offset + glm::vec3 panOffset = right * deltaX * panScale + up * deltaY * panScale; + + // Set both target AND current immediately (no smoothing) + m_targetFocusPoint += panOffset; + m_currentFocusPoint += panOffset; + m_viewMatrixDirty = true; +} + +void OrbitCamera::Update(float deltaTime) { + // Smooth interpolation towards target values + float lerpFactor = 1.0f - std::pow(m_smoothingFactor, deltaTime); + + m_currentDistance = glm::mix(m_currentDistance, m_targetDistance, lerpFactor); + m_currentAzimuth = LerpAngle(m_currentAzimuth, m_targetAzimuth, lerpFactor); + m_currentElevation = glm::mix(m_currentElevation, m_targetElevation, lerpFactor); + m_currentFocusPoint = glm::mix(m_currentFocusPoint, m_targetFocusPoint, lerpFactor); + + UpdateCurrentPosition(); +} + +void OrbitCamera::FrameAll(glm::vec3 center, float radius) { + SetFocusToSelection(center, radius); +} + +void OrbitCamera::SetFocusToSelection(glm::vec3 selectionCenter, float selectionRadius) { + m_targetFocusPoint = selectionCenter; + + // Adjust distance based on selection size + if (selectionRadius > 0.0f) { + float recommendedDistance = selectionRadius * 3.0f; // Good viewing distance + recommendedDistance = glm::clamp(recommendedDistance, m_minDistance, m_maxDistance); + m_targetDistance = recommendedDistance; + } + + std::cout << "OrbitCamera: Focus set to selection at (" + << selectionCenter.x << ", " << selectionCenter.y << ", " << selectionCenter.z + << ") with radius " << selectionRadius << std::endl; +} + +glm::mat4 OrbitCamera::GetViewMatrix() const { + if (m_viewMatrixDirty) { + glm::mat4 viewMatrix = glm::lookAt(m_currentPosition, m_currentFocusPoint, glm::vec3(0.0f, 1.0f, 0.0f)); + m_viewMatrixDirty = false; + return viewMatrix; + } + return glm::lookAt(m_currentPosition, m_currentFocusPoint, glm::vec3(0.0f, 1.0f, 0.0f)); +} + +glm::mat4 OrbitCamera::GetProjectionMatrix(float aspectRatio) const { + return glm::perspective(glm::radians(m_fov), aspectRatio, 0.1f, 256.0f); +} + +void OrbitCamera::SetSensitivity(float orbit, float pan, float zoom) { + m_orbitSensitivity = orbit; + m_panSensitivity = pan; + m_zoomSensitivity = zoom; +} + +void OrbitCamera::SetConstraints(float minDist, float maxDist, float minElev, float maxElev) { + m_minDistance = minDist; + m_maxDistance = maxDist; + m_minElevation = minElev; + m_maxElevation = maxElev; +} + +void OrbitCamera::SetSmoothingFactor(float factor) { + m_smoothingFactor = glm::clamp(factor, 0.0f, 1.0f); +} + +void OrbitCamera::SetFocusToSelectionImmediate(glm::vec3 center, float radius) { + m_targetFocusPoint = center; + m_currentFocusPoint = center; // Immediate change, no smoothing + + // Adjust distance based on selection size + if (radius > 0.0f) { + float recommendedDistance = radius * 3.0f; // Good viewing distance + recommendedDistance = glm::clamp(recommendedDistance, m_minDistance, m_maxDistance); + m_targetDistance = recommendedDistance; + m_currentDistance = recommendedDistance; // Immediate change, no smoothing + } + + UpdateCurrentPosition(); + m_viewMatrixDirty = true; +} + +void OrbitCamera::FrameAllImmediate(glm::vec3 center, float radius) { + SetFocusToSelectionImmediate(center, radius); +} + +// Private helper methods +void OrbitCamera::CartesianToSpherical(glm::vec3 position, glm::vec3 center, + float& distance, float& azimuth, float& elevation) { + glm::vec3 offset = position - center; + distance = glm::length(offset); + + if (distance < 0.001f) { + // Very close to center, use default values + azimuth = 0.0f; + elevation = 0.0f; + return; + } + + // Normalize offset for angle calculations + glm::vec3 normalized = offset / distance; + + // Calculate azimuth (horizontal angle) - using atan for proper quadrant + azimuth = glm::atan(normalized.z, normalized.x); + + // Calculate elevation (vertical angle) - use asin but clamp input to avoid NaN + float sinElevation = glm::clamp(normalized.y, -1.0f, 1.0f); + elevation = glm::asin(sinElevation); +} + +glm::vec3 OrbitCamera::SphericalToCartesian(float distance, float azimuth, float elevation, + glm::vec3 focusPoint) { + // Standard spherical coordinate conversion (input in radians) + float x = distance * glm::cos(elevation) * glm::cos(azimuth); + float y = distance * glm::sin(elevation); + float z = distance * glm::cos(elevation) * glm::sin(azimuth); + return glm::vec3(x, y, z) + focusPoint; +} + +void OrbitCamera::ClampConstraints() { + m_targetDistance = glm::clamp(m_targetDistance, m_minDistance, m_maxDistance); + m_targetElevation = glm::clamp(m_targetElevation, glm::radians(m_minElevation), glm::radians(m_maxElevation)); + + // Normalize azimuth to 0-2π range + while (m_targetAzimuth > 2.0f * static_cast(M_PI)) m_targetAzimuth -= 2.0f * static_cast(M_PI); + while (m_targetAzimuth < 0.0f) m_targetAzimuth += 2.0f * static_cast(M_PI); +} + +void OrbitCamera::UpdateCurrentPosition() { + m_currentPosition = SphericalToCartesian(m_currentDistance, m_currentAzimuth, m_currentElevation, m_currentFocusPoint); + m_viewMatrixDirty = true; +} + +float OrbitCamera::LerpAngle(float from, float to, float t) const { + // Handle angle wraparound for smooth interpolation (using radians) + float difference = to - from; + + // Wrap difference to [-π, π] range + if (difference > static_cast(M_PI)) difference -= 2.0f * static_cast(M_PI); + if (difference < -static_cast(M_PI)) difference += 2.0f * static_cast(M_PI); + + return from + difference * t; +} \ No newline at end of file diff --git a/src/core/Camera.h b/src/core/Camera.h new file mode 100644 index 00000000..b9a4b577 --- /dev/null +++ b/src/core/Camera.h @@ -0,0 +1,93 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#pragma once + +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +// Enhanced Camera System with Maya-style controls +class OrbitCamera { +public: + // Constructor + OrbitCamera(glm::vec3 initialPosition = glm::vec3(0.0f, 0.0f, 8.0f), + glm::vec3 focusPoint = glm::vec3(0.0f, 0.0f, 0.0f)); + + // Core camera operations + void Orbit(float deltaAzimuth, float deltaElevation, float deltaTime); + void Pan(float deltaX, float deltaY, float deltaTime); + void Zoom(float deltaDistance, float deltaTime); + void ZoomImmediate(float deltaDistance, float deltaTime); + void PanImmediate(float deltaX, float deltaY, float deltaTime); + + void Update(float deltaTime); + + // Camera focus operations + void FrameAll(glm::vec3 center, float radius); + void SetFocusToSelection(glm::vec3 center, float radius); + + // Matrix access + glm::mat4 GetViewMatrix() const; + glm::mat4 GetProjectionMatrix(float aspectRatio) const; + + // Camera state + glm::vec3 GetPosition() const { return m_currentPosition; } + glm::vec3 GetFocusPoint() const { return m_currentFocusPoint; } + float GetDistance() const { return m_currentDistance; } + + // Settings + void SetSensitivity(float orbit, float pan, float zoom); + void SetConstraints(float minDist, float maxDist, float minElev, float maxElev); + void SetSmoothingFactor(float factor); + + // Immediate operations (no smoothing) + void SetFocusToSelectionImmediate(glm::vec3 center, float radius); + void FrameAllImmediate(glm::vec3 center, float radius); + +private: + // Camera parameters + glm::vec3 m_currentPosition; + glm::vec3 m_currentFocusPoint; + glm::vec3 m_targetFocusPoint; + + float m_currentDistance; + float m_targetDistance; + float m_currentAzimuth; // Horizontal rotation (radians) + float m_targetAzimuth; + float m_currentElevation; // Vertical rotation (radians) + float m_targetElevation; + + // Camera settings + float m_fov; + float m_smoothingFactor; + float m_orbitSensitivity; + float m_panSensitivity; + float m_zoomSensitivity; + + // Constraints + float m_minDistance; + float m_maxDistance; + float m_minElevation; + float m_maxElevation; + + // State flags + mutable bool m_viewMatrixDirty; + + // Helper functions + void CartesianToSpherical(glm::vec3 position, glm::vec3 focusPoint, + float& distance, float& azimuth, float& elevation); + glm::vec3 SphericalToCartesian(float distance, float azimuth, float elevation, + glm::vec3 focusPoint); + void ClampConstraints(); + void UpdateCurrentPosition(); + float LerpAngle(float from, float to, float t) const; +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 00000000..381d0d0b --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,15 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#include "core/Application.h" +#include "Entrypoints.h" + +// Alias Application as VulkanExample for the entry point macro +using VulkanExample = Application; + +VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/src/scene/ProceduralGeometry.cpp b/src/scene/ProceduralGeometry.cpp new file mode 100644 index 00000000..93efd3e9 --- /dev/null +++ b/src/scene/ProceduralGeometry.cpp @@ -0,0 +1,336 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#include "ProceduralGeometry.h" +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +ProceduralShape ProceduralGeometry::generateCube(float width, float height, float depth) { + ProceduralShape shape; + shape.name = "Cube"; + shape.type = 0; + shape.params.width = width; + shape.params.height = height; + shape.params.depth = depth; + + float w = width * 0.5f; + float h = height * 0.5f; + float d = depth * 0.5f; + + // Define 24 vertices (4 per face, 6 faces) with colors + shape.vertices = { + // Front face (red) + {{-w, -h, d}, {0, 0, 1}, {1, 0, 0}}, {{ w, -h, d}, {0, 0, 1}, {1, 0, 0}}, + {{ w, h, d}, {0, 0, 1}, {1, 0, 0}}, {{-w, h, d}, {0, 0, 1}, {1, 0, 0}}, + // Back face (green) + {{ w, -h, -d}, {0, 0, -1}, {0, 1, 0}}, {{-w, -h, -d}, {0, 0, -1}, {0, 1, 0}}, + {{-w, h, -d}, {0, 0, -1}, {0, 1, 0}}, {{ w, h, -d}, {0, 0, -1}, {0, 1, 0}}, + // Left face (blue) + {{-w, -h, -d}, {-1, 0, 0}, {0, 0, 1}}, {{-w, -h, d}, {-1, 0, 0}, {0, 0, 1}}, + {{-w, h, d}, {-1, 0, 0}, {0, 0, 1}}, {{-w, h, -d}, {-1, 0, 0}, {0, 0, 1}}, + // Right face (yellow) + {{ w, -h, d}, {1, 0, 0}, {1, 1, 0}}, {{ w, -h, -d}, {1, 0, 0}, {1, 1, 0}}, + {{ w, h, -d}, {1, 0, 0}, {1, 1, 0}}, {{ w, h, d}, {1, 0, 0}, {1, 1, 0}}, + // Top face (magenta) + {{-w, h, d}, {0, 1, 0}, {1, 0, 1}}, {{ w, h, d}, {0, 1, 0}, {1, 0, 1}}, + {{ w, h, -d}, {0, 1, 0}, {1, 0, 1}}, {{-w, h, -d}, {0, 1, 0}, {1, 0, 1}}, + // Bottom face (cyan) + {{-w, -h, -d}, {0, -1, 0}, {0, 1, 1}}, {{ w, -h, -d}, {0, -1, 0}, {0, 1, 1}}, + {{ w, -h, d}, {0, -1, 0}, {0, 1, 1}}, {{-w, -h, d}, {0, -1, 0}, {0, 1, 1}} + }; + + // Define indices for 12 triangles (2 per face) + shape.indices = { + 0,1,2, 0,2,3, // Front + 4,5,6, 4,6,7, // Back + 8,9,10, 8,10,11, // Left + 12,13,14, 12,14,15, // Right + 16,17,18, 16,18,19, // Top + 20,21,22, 20,22,23 // Bottom + }; + + return shape; +} + +ProceduralShape ProceduralGeometry::generateSphere(float radius, int segments) { + ProceduralShape shape; + shape.name = "Sphere"; + shape.type = 1; + shape.params.radius = radius; + shape.params.segments = segments; + + // Generate sphere vertices using spherical coordinates + for (int lat = 0; lat <= segments; ++lat) { + float theta = lat * static_cast(M_PI) / segments; + float sinTheta = sin(theta); + float cosTheta = cos(theta); + + for (int lon = 0; lon <= segments; ++lon) { + float phi = lon * 2 * static_cast(M_PI) / segments; + float sinPhi = sin(phi); + float cosPhi = cos(phi); + + glm::vec3 pos(radius * sinTheta * cosPhi, radius * cosTheta, radius * sinTheta * sinPhi); + glm::vec3 normal = glm::normalize(pos); + glm::vec3 color(0.8f, 0.8f, 0.8f); // Light gray color for sphere + + shape.vertices.push_back({pos, normal, color}); + } + } + + // Generate indices + for (int lat = 0; lat < segments; ++lat) { + for (int lon = 0; lon < segments; ++lon) { + int first = lat * (segments + 1) + lon; + int second = first + segments + 1; + + shape.indices.push_back(first); + shape.indices.push_back(second); + shape.indices.push_back(first + 1); + + shape.indices.push_back(second); + shape.indices.push_back(second + 1); + shape.indices.push_back(first + 1); + } + } + + return shape; +} + +ProceduralShape ProceduralGeometry::generatePlane(float width, float height, int subdivisions) { + ProceduralShape shape; + shape.name = "Plane"; + shape.type = 3; + shape.params.width = width; + shape.params.height = height; + shape.params.subdivisions = subdivisions; + + float w = width * 0.5f; + float h = height * 0.5f; + + // Simple quad for now + shape.vertices = { + {{-w, 0, -h}, {0, 1, 0}, {0.5f, 0.5f, 0.5f}}, // Gray plane + {{ w, 0, -h}, {0, 1, 0}, {0.5f, 0.5f, 0.5f}}, + {{ w, 0, h}, {0, 1, 0}, {0.5f, 0.5f, 0.5f}}, + {{-w, 0, h}, {0, 1, 0}, {0.5f, 0.5f, 0.5f}} + }; + + shape.indices = {0, 1, 2, 0, 2, 3}; + + return shape; +} + +ProceduralShape ProceduralGeometry::generateCone(float radius, float height, int segments) { + ProceduralShape shape; + shape.name = "Cone"; + shape.type = 4; // Cone type + shape.params.radius = radius; + shape.params.height = height; + shape.params.segments = segments; + + // Add tip vertex (red cone tip) + shape.vertices.push_back({{0, height * 0.5f, 0}, {0, 1, 0}, {1.0f, 0.0f, 0.0f}}); + + // Add center vertex for base (dark red) + shape.vertices.push_back({{0, -height * 0.5f, 0}, {0, -1, 0}, {0.5f, 0.0f, 0.0f}}); + + // Generate base vertices + for (int i = 0; i <= segments; ++i) { + float angle = static_cast(i) / segments * 2.0f * static_cast(M_PI); + float x = cos(angle) * radius; + float z = sin(angle) * radius; + glm::vec3 color(0.8f, 0.2f, 0.2f); // Light red + + // Base vertex + shape.vertices.push_back({{x, -height * 0.5f, z}, {0, -1, 0}, color}); + + // Side vertex (for side triangles) + glm::vec3 sideNormal = glm::normalize(glm::vec3(x, radius / height, z)); + shape.vertices.push_back({{x, -height * 0.5f, z}, sideNormal, color}); + } + + // Generate indices + // Side triangles (tip to base edge) + for (int i = 0; i < segments; ++i) { + int baseStart = 2 + segments + 1; + shape.indices.push_back(0); // tip + shape.indices.push_back(baseStart + (i + 1) * 2); + shape.indices.push_back(baseStart + i * 2); + } + + // Base triangles + for (int i = 0; i < segments; ++i) { + shape.indices.push_back(1); // center + shape.indices.push_back(2 + i); + shape.indices.push_back(2 + ((i + 1) % (segments + 1))); + } + + return shape; +} + +ProceduralShape ProceduralGeometry::generateCylinder(float radius, float height, int segments) { + ProceduralShape shape; + shape.name = "Cylinder"; + shape.type = 5; // Cylinder type + shape.params.radius = radius; + shape.params.height = height; + shape.params.segments = segments; + + float halfHeight = height * 0.5f; + + // Add center vertices for caps (blue cylinder) + shape.vertices.push_back({{0, halfHeight, 0}, {0, 1, 0}, {0.0f, 0.0f, 1.0f}}); // top center + shape.vertices.push_back({{0, -halfHeight, 0}, {0, -1, 0}, {0.0f, 0.0f, 1.0f}}); // bottom center + + // Generate side vertices (double for proper normals) + for (int i = 0; i <= segments; ++i) { + float angle = static_cast(i) / segments * 2.0f * static_cast(M_PI); + float x = cos(angle) * radius; + float z = sin(angle) * radius; + glm::vec3 normal = glm::normalize(glm::vec3(x, 0, z)); + glm::vec3 color(0.2f, 0.4f, 1.0f); // Light blue + + // Top vertices + shape.vertices.push_back({{x, halfHeight, z}, {0, 1, 0}, color}); // top cap + shape.vertices.push_back({{x, halfHeight, z}, normal, color}); // top side + + // Bottom vertices + shape.vertices.push_back({{x, -halfHeight, z}, {0, -1, 0}, color}); // bottom cap + shape.vertices.push_back({{x, -halfHeight, z}, normal, color}); // bottom side + } + + // Generate indices + for (int i = 0; i < segments; ++i) { + int topCapStart = 2; + int bottomCapStart = 4; + + // Top cap triangles + shape.indices.push_back(0); // top center + shape.indices.push_back(topCapStart + ((i + 1) % (segments + 1)) * 4); + shape.indices.push_back(topCapStart + i * 4); + + // Bottom cap triangles + shape.indices.push_back(1); // bottom center + shape.indices.push_back(bottomCapStart + i * 4); + shape.indices.push_back(bottomCapStart + ((i + 1) % (segments + 1)) * 4); + + // Side quads (as two triangles) + int topSide1 = topCapStart + 1 + i * 4; + int topSide2 = topCapStart + 1 + ((i + 1) % (segments + 1)) * 4; + int bottomSide1 = bottomCapStart + 1 + i * 4; + int bottomSide2 = bottomCapStart + 1 + ((i + 1) % (segments + 1)) * 4; + + // First triangle + shape.indices.push_back(topSide1); + shape.indices.push_back(bottomSide1); + shape.indices.push_back(topSide2); + + // Second triangle + shape.indices.push_back(topSide2); + shape.indices.push_back(bottomSide1); + shape.indices.push_back(bottomSide2); + } + + return shape; +} + +ProceduralShape ProceduralGeometry::generateTorus(float majorRadius, float minorRadius, + int majorSegments, int minorSegments) { + ProceduralShape shape; + shape.name = "Torus"; + shape.type = 6; // Torus type + shape.params.majorRadius = majorRadius; + shape.params.minorRadius = minorRadius; + shape.params.segments = majorSegments; + shape.params.subdivisions = minorSegments; + + // Generate vertices + for (int i = 0; i <= majorSegments; ++i) { + float majorAngle = static_cast(i) / majorSegments * 2.0f * static_cast(M_PI); + float cosMajor = cos(majorAngle); + float sinMajor = sin(majorAngle); + + for (int j = 0; j <= minorSegments; ++j) { + float minorAngle = static_cast(j) / minorSegments * 2.0f * static_cast(M_PI); + float cosMinor = cos(minorAngle); + float sinMinor = sin(minorAngle); + + // Calculate position + float x = (majorRadius + minorRadius * cosMinor) * cosMajor; + float y = minorRadius * sinMinor; + float z = (majorRadius + minorRadius * cosMinor) * sinMajor; + + // Calculate normal + glm::vec3 center(majorRadius * cosMajor, 0, majorRadius * sinMajor); + glm::vec3 position(x, y, z); + glm::vec3 normal = glm::normalize(position - center); + + // Use orange color for torus + glm::vec3 color(1.0f, 0.5f, 0.0f); + + shape.vertices.push_back({{x, y, z}, normal, color}); + } + } + + // Generate indices + for (int i = 0; i < majorSegments; ++i) { + for (int j = 0; j < minorSegments; ++j) { + int current = i * (minorSegments + 1) + j; + int next = ((i + 1) % (majorSegments + 1)) * (minorSegments + 1) + j; + + // First triangle + shape.indices.push_back(current); + shape.indices.push_back(next); + shape.indices.push_back(current + 1); + + // Second triangle + shape.indices.push_back(next); + shape.indices.push_back(next + 1); + shape.indices.push_back(current + 1); + } + } + + return shape; +} + +ProceduralShape ProceduralGeometry::generateGrid(float size, int divisions) { + ProceduralShape shape; + shape.name = "Grid"; + shape.type = 6; // Grid type + shape.params.width = size; + shape.params.subdivisions = divisions; + + float step = size / divisions; + float halfSize = size * 0.5f; + + // Create grid lines (white grid) + glm::vec3 gridColor(1.0f, 1.0f, 1.0f); + for (int i = 0; i <= divisions; ++i) { + float pos = -halfSize + i * step; + + // Horizontal lines + shape.vertices.push_back({{-halfSize, 0, pos}, {0, 1, 0}, gridColor}); + shape.vertices.push_back({{ halfSize, 0, pos}, {0, 1, 0}, gridColor}); + + // Vertical lines + shape.vertices.push_back({{pos, 0, -halfSize}, {0, 1, 0}, gridColor}); + shape.vertices.push_back({{pos, 0, halfSize}, {0, 1, 0}, gridColor}); + } + + // Generate indices for lines + for (int i = 0; i < (divisions + 1) * 4; i += 2) { + shape.indices.push_back(i); + shape.indices.push_back(i + 1); + } + + return shape; +} \ No newline at end of file diff --git a/src/scene/ProceduralGeometry.h b/src/scene/ProceduralGeometry.h new file mode 100644 index 00000000..ce00501f --- /dev/null +++ b/src/scene/ProceduralGeometry.h @@ -0,0 +1,51 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#pragma once + +#include +#include +#include + +// Procedural vertex structure +struct ProceduralVertex { + glm::vec3 position; + glm::vec3 normal; + glm::vec3 color; +}; + +// Shape data structure +struct ProceduralShape { + std::vector vertices; + std::vector indices; + std::string name; + int type; // 0=cube, 1=sphere, 2=cylinder, 3=plane, 4=cone, 5=torus + + // Shape parameters + struct { + float width = 2.0f, height = 2.0f, depth = 2.0f; + int subdivisions = 1; + float radius = 1.0f; + int segments = 16; + float majorRadius = 1.0f, minorRadius = 0.3f; + } params; +}; + +// Procedural geometry generation class +class ProceduralGeometry { +public: + // Shape generation methods + static ProceduralShape generateCube(float width = 4.0f, float height = 4.0f, float depth = 4.0f); + static ProceduralShape generateSphere(float radius = 1.0f, int segments = 16); + static ProceduralShape generatePlane(float width = 2.0f, float height = 2.0f, int subdivisions = 1); + static ProceduralShape generateCone(float radius = 1.0f, float height = 2.0f, int segments = 16); + static ProceduralShape generateCylinder(float radius = 1.0f, float height = 2.0f, int segments = 16); + static ProceduralShape generateTorus(float majorRadius = 1.0f, float minorRadius = 0.3f, + int majorSegments = 16, int minorSegments = 8); + static ProceduralShape generateGrid(float size = 10.0f, int divisions = 10); +}; \ No newline at end of file diff --git a/src/scene/SceneManager.cpp b/src/scene/SceneManager.cpp new file mode 100644 index 00000000..d621b945 --- /dev/null +++ b/src/scene/SceneManager.cpp @@ -0,0 +1,154 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#include "SceneManager.h" +#include +#include +#include "device/VulkanDevice.h" +#include "memory/VulkanBuffer.h" + +SceneManager::SceneManager() { +} + +SceneManager::~SceneManager() { +} + +void SceneManager::addObject(const std::string& shapeName, const std::string& shapeType) { + // Add new object to collection + std::string fullName = shapeName + " " + std::to_string(getObjectCount() + 1); + std::cout << "SceneManager: Adding object '" << fullName << "' of type '" << shapeType << "'" << std::endl; + + objects.emplace_back(fullName, "Procedural"); + + // Generate actual geometry based on shape type + SceneObject& newObj = objects.back(); + newObj.subtype = shapeType; // Set the shape subtype (Cube, Sphere, etc.) + + // Place all objects at world origin (0,0,0) + // Users can move them via transform controls in Inspector + newObj.position.x = 0.0f; + newObj.position.y = 0.0f; + newObj.position.z = 0.0f; + + std::cout << "SceneManager: Object positioned at origin (0, 0, 0)" << std::endl; + + // Initialize procedural parameters based on shape type (use regenerateGeometry to create initial geometry) + newObj.regenerateGeometry(); + std::cout << "SceneManager: Generated " << newObj.vertices.size() << " vertices and " << newObj.indices.size() << " indices" << std::endl; + + // Create Vulkan buffers for the new object if device is available + if (device) { + createBuffersForObject(newObj, device); + } else { + std::cout << "SceneManager: Warning - No Vulkan device available for buffer creation" << std::endl; + } + + std::cout << "SceneManager: Object creation completed. Total objects: " << getObjectCount() << std::endl; +} + +void SceneManager::removeObject(size_t index) { + if (index < objects.size()) { + objects.erase(objects.begin() + index); + + // Adjust selection index + if (selectedIndex >= static_cast(objects.size())) { + selectedIndex = static_cast(objects.size()) - 1; + } + } +} + +void SceneManager::clearScene() { + objects.clear(); + selectedIndex = -1; +} + +void SceneManager::setSelectedObject(int index) { + if (index >= 0 && index < static_cast(objects.size())) { + selectedIndex = index; + } else { + selectedIndex = -1; + } +} + +SceneObject* SceneManager::getSelectedObject() { + if (selectedIndex >= 0 && selectedIndex < static_cast(objects.size())) { + return &objects[selectedIndex]; + } + return nullptr; +} + +const SceneObject* SceneManager::getSelectedObject() const { + if (selectedIndex >= 0 && selectedIndex < static_cast(objects.size())) { + return &objects[selectedIndex]; + } + return nullptr; +} + +void SceneManager::createBuffersForObject(SceneObject& obj, vks::VulkanDevice* device) { + if (!device) { + std::cout << "Error: VulkanDevice not available for buffer creation" << std::endl; + return; + } + + if (obj.vertices.empty() || obj.indices.empty()) { + std::cout << "Error: Cannot create buffers for " << obj.name << " - geometry data is empty" << std::endl; + return; + } + + if (obj.vulkanBuffers.buffersCreated) { + std::cout << "Info: Buffers already created for " << obj.name << std::endl; + return; + } + + try { + std::cout << "Creating Vulkan buffers for " << obj.name << " with " << obj.vertices.size() << " vertices and " << obj.indices.size() << " indices" << std::endl; + + // Create vertex buffer + VkDeviceSize vertexBufferSize = obj.vertices.size() * sizeof(ProceduralVertex); + VkResult result = device->createBuffer( + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &obj.vulkanBuffers.vertexBuffer, + vertexBufferSize, + (void*)obj.vertices.data() + ); + + if (result != VK_SUCCESS) { + std::cout << "Failed to create vertex buffer for " << obj.name << " - VkResult: " << result << std::endl; + return; + } + + // Create index buffer + VkDeviceSize indexBufferSize = obj.indices.size() * sizeof(uint32_t); + result = device->createBuffer( + VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &obj.vulkanBuffers.indexBuffer, + indexBufferSize, + (void*)obj.indices.data() + ); + + if (result != VK_SUCCESS) { + std::cout << "Failed to create index buffer for " << obj.name << " - VkResult: " << result << std::endl; + obj.vulkanBuffers.vertexBuffer.destroy(); + return; + } + + obj.vulkanBuffers.buffersCreated = true; + std::cout << "Successfully created Vulkan buffers for " << obj.name << std::endl; + + } catch (const std::exception& e) { + std::cout << "Exception creating buffers for " << obj.name << ": " << e.what() << std::endl; + } +} + +void SceneManager::destroyAllBuffers(vks::VulkanDevice* device) { + for (auto& obj : objects) { + obj.destroyBuffers(device); + } +} \ No newline at end of file diff --git a/src/scene/SceneManager.h b/src/scene/SceneManager.h new file mode 100644 index 00000000..2fc46126 --- /dev/null +++ b/src/scene/SceneManager.h @@ -0,0 +1,53 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#pragma once + +#include "SceneObject.h" +#include +#include + +// Forward declarations +namespace vks { + class VulkanDevice; +} + +// Simple scene management +class SceneManager { +public: + SceneManager(); + ~SceneManager(); + + // Object management + void addObject(const std::string& shapeName, const std::string& shapeType); + void removeObject(size_t index); + void clearScene(); + + // Selection management + void setSelectedObject(int index); + SceneObject* getSelectedObject(); + const SceneObject* getSelectedObject() const; + int getSelectedIndex() const { return selectedIndex; } + + // Object access + std::vector& getObjects() { return objects; } + const std::vector& getObjects() const { return objects; } + SceneObject& getObject(size_t index) { return objects[index]; } + const SceneObject& getObject(size_t index) const { return objects[index]; } + size_t getObjectCount() const { return objects.size(); } + + // Vulkan buffer management + void createBuffersForObject(SceneObject& obj, vks::VulkanDevice* device); + void destroyAllBuffers(vks::VulkanDevice* device); + void setVulkanDevice(vks::VulkanDevice* dev) { device = dev; } + +private: + std::vector objects; + int selectedIndex = -1; + vks::VulkanDevice* device = nullptr; +}; \ No newline at end of file diff --git a/src/scene/SceneObject.cpp b/src/scene/SceneObject.cpp new file mode 100644 index 00000000..3eb0314d --- /dev/null +++ b/src/scene/SceneObject.cpp @@ -0,0 +1,108 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#include "SceneObject.h" +#include "ProceduralGeometry.h" +#include "device/VulkanDevice.h" + +void SceneObject::destroyBuffers(vks::VulkanDevice* device) { + if (vulkanBuffers.buffersCreated) { + vulkanBuffers.vertexBuffer.destroy(); + vulkanBuffers.indexBuffer.destroy(); + vulkanBuffers.buffersCreated = false; + } +} + +glm::vec3 SceneObject::getBoundingBoxCenter() const { + if (vertices.empty()) return position; + + glm::vec3 minPos = vertices[0].position; + glm::vec3 maxPos = vertices[0].position; + + for (const auto& vertex : vertices) { + minPos = glm::min(minPos, vertex.position); + maxPos = glm::max(maxPos, vertex.position); + } + + // Calculate local bounding box center and transform to world space + glm::vec3 localCenter = (minPos + maxPos) * 0.5f; + + // Apply scale to local center, then translate to world position + // This matches Sascha's glTF approach: world_space = position + local_space * scale + glm::vec3 worldCenter = position + localCenter * scale; + + return worldCenter; +} + +float SceneObject::getBoundingRadius() const { + if (vertices.empty()) return 1.0f; + + // Calculate local bounding box in model space + glm::vec3 minPos = vertices[0].position; + glm::vec3 maxPos = vertices[0].position; + + for (const auto& vertex : vertices) { + minPos = glm::min(minPos, vertex.position); + maxPos = glm::max(maxPos, vertex.position); + } + + // Calculate radius using Sascha's glTF approach: distance between min/max corners + float localRadius = glm::distance(minPos, maxPos) / 2.0f; + + // Apply scale transformation to radius + // Use the maximum scale component for worst-case radius calculation + float maxScaleComponent = std::max({scale.x, scale.y, scale.z}); + float worldRadius = localRadius * maxScaleComponent; + + return std::max(worldRadius, 0.5f); // Minimum radius of 0.5 +} + +void SceneObject::regenerateGeometry() { + if (type != "Procedural") return; + + ProceduralShape shape; + + if (subtype == "Cube") { + shape = ProceduralGeometry::generateCube(proceduralParams.cubeWidth, + proceduralParams.cubeHeight, + proceduralParams.cubeDepth); + } else if (subtype == "Sphere") { + shape = ProceduralGeometry::generateSphere(proceduralParams.sphereRadius, + proceduralParams.sphereSegments); + } else if (subtype == "Cylinder") { + shape = ProceduralGeometry::generateCylinder(proceduralParams.cylinderRadius, + proceduralParams.cylinderHeight, + proceduralParams.cylinderSegments); + } else if (subtype == "Cone") { + shape = ProceduralGeometry::generateCone(proceduralParams.coneRadius, + proceduralParams.coneHeight, + proceduralParams.coneSegments); + } else if (subtype == "Plane") { + shape = ProceduralGeometry::generatePlane(proceduralParams.planeWidth, + proceduralParams.planeHeight, + proceduralParams.planeSubdivisions); + } else if (subtype == "Torus") { + shape = ProceduralGeometry::generateTorus(proceduralParams.torusMajorRadius, + proceduralParams.torusMinorRadius, + proceduralParams.torusMajorSegments, + proceduralParams.torusMinorSegments); + } + + // Update geometry data + vertices = shape.vertices; + indices = shape.indices; + + // Destroy existing buffers if they exist (to handle size changes) + if (vulkanBuffers.buffersCreated) { + vulkanBuffers.vertexBuffer.destroy(); + vulkanBuffers.indexBuffer.destroy(); + } + + // Mark buffers as needing recreation + vulkanBuffers.buffersCreated = false; +} \ No newline at end of file diff --git a/src/scene/SceneObject.h b/src/scene/SceneObject.h new file mode 100644 index 00000000..3ff227ce --- /dev/null +++ b/src/scene/SceneObject.h @@ -0,0 +1,91 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#pragma once + +#include "ProceduralGeometry.h" +#include +#include +#include +#include "memory/VulkanBuffer.h" + +// Forward declaration for Vulkan device +namespace vks { + class VulkanDevice; +} + +// Scene Object for basic hierarchy +struct SceneObject { + std::string name; + std::string type; + std::string subtype; // For procedural shapes (Cube, Sphere, etc.) + bool visible = true; + + // Simple geometry data (for procedural shapes) + std::vector vertices; + std::vector indices; + glm::vec3 position = {0.0f, 0.0f, 0.0f}; // Place objects at world origin + glm::vec3 rotation = {0.0f, 0.0f, 0.0f}; + glm::vec3 scale = {1.0f, 1.0f, 1.0f}; // Default unit scale + + // Procedural shape parameters (for real-time editing) + struct ProceduralParams { + // Cube parameters + float cubeWidth = 2.0f; + float cubeHeight = 2.0f; + float cubeDepth = 2.0f; + int cubeSubdivisions = 1; + + // Sphere parameters + float sphereRadius = 1.0f; + int sphereSegments = 16; + + // Cylinder parameters + float cylinderRadius = 1.0f; + float cylinderHeight = 2.0f; + int cylinderSegments = 16; + + // Cone parameters + float coneRadius = 1.0f; + float coneHeight = 2.0f; + int coneSegments = 16; + + // Plane parameters + float planeWidth = 2.0f; + float planeHeight = 2.0f; + int planeSubdivisions = 1; + + // Torus parameters + float torusMajorRadius = 1.0f; + float torusMinorRadius = 0.3f; + int torusMajorSegments = 16; + int torusMinorSegments = 8; + } proceduralParams; + + // Persistent Vulkan buffers (created once, used multiple times) + struct VulkanBuffers { + vks::Buffer vertexBuffer; + vks::Buffer indexBuffer; + bool buffersCreated = false; + } vulkanBuffers; + + SceneObject(const std::string& objName, const std::string& objType = "Object") + : name(objName), type(objType) {} + + // Cleanup buffers when object is destroyed + void destroyBuffers(vks::VulkanDevice* device); + + // Calculate bounding box center for camera focus + glm::vec3 getBoundingBoxCenter() const; + + // Calculate bounding radius for camera focus + float getBoundingRadius() const; + + // Regenerate geometry based on current procedural parameters + void regenerateGeometry(); +}; \ No newline at end of file diff --git a/src/ui/UIManager.cpp b/src/ui/UIManager.cpp new file mode 100644 index 00000000..1c7d75c1 --- /dev/null +++ b/src/ui/UIManager.cpp @@ -0,0 +1,1046 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#include "UIManager.h" +#include "../core/Application.h" +#include + +UIManager::UIManager(Application *app) : application(app) +{ + device = nullptr; // Will be set when proper Vulkan integration is complete + uiSettings = nullptr; + sceneManager = nullptr; + + std::cout << "UIManager: Creating ImGui context" << std::endl; + ImGui::CreateContext(); + + // Set up basic ImGui configuration + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; + + std::cout << "UIManager initialized with ImGui context" << std::endl; +} + +UIManager::~UIManager() +{ + ImGui::DestroyContext(); + + // TODO: Release all Vulkan resources when proper integration is complete + // vertexBuffer.destroy(); + // indexBuffer.destroy(); + // vkDestroyImage(device->logicalDevice, fontImage, nullptr); + // vkDestroyImageView(device->logicalDevice, fontView, nullptr); + // vkFreeMemory(device->logicalDevice, fontMemory, nullptr); + // vkDestroySampler(device->logicalDevice, sampler, nullptr); + // vkDestroyDescriptorSetLayout(device->logicalDevice, descriptorSetLayout, nullptr); + // vkDestroyDescriptorPool(device->logicalDevice, descriptorPool, nullptr); + // vkDestroyPipelineLayout(device->logicalDevice, pipelineLayout, nullptr); + // vkDestroyPipeline(device->logicalDevice, pipeline, nullptr); + + std::cout << "UIManager destroyed" << std::endl; +} + +void UIManager::init(float width, float height) +{ + // Color scheme - Vulkan red theme as default + vulkanStyle = ImGui::GetStyle(); + vulkanStyle.Colors[ImGuiCol_TitleBg] = ImVec4(1.0f, 0.0f, 0.0f, 0.6f); + vulkanStyle.Colors[ImGuiCol_TitleBgActive] = ImVec4(1.0f, 0.0f, 0.0f, 0.8f); + vulkanStyle.Colors[ImGuiCol_MenuBarBg] = ImVec4(1.0f, 0.0f, 0.0f, 0.4f); + vulkanStyle.Colors[ImGuiCol_Header] = ImVec4(1.0f, 0.0f, 0.0f, 0.4f); + vulkanStyle.Colors[ImGuiCol_CheckMark] = ImVec4(0.0f, 1.0f, 0.0f, 1.0f); + + // Set default style + setStyle(0); + + // Configure ImGui IO properly + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2(width, height); + io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f); + + // Enable keyboard navigation + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + + // Set backend flags to indicate we handle mouse/keyboard + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; + + // Set up font atlas (required for ImGui to work) + io.Fonts->AddFontDefault(); + unsigned char* pixels; + int width_atlas, height_atlas; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width_atlas, &height_atlas); + + // For now, we'll create a minimal font setup + // Full Vulkan font texture will be implemented later + io.Fonts->TexID = 0; // Set to null for now + + // Set up key mapping for basic input + io.KeyMap[ImGuiKey_Tab] = 0x09; // VK_TAB + io.KeyMap[ImGuiKey_LeftArrow] = 0x25; // VK_LEFT + io.KeyMap[ImGuiKey_RightArrow] = 0x27; // VK_RIGHT + io.KeyMap[ImGuiKey_UpArrow] = 0x26; // VK_UP + io.KeyMap[ImGuiKey_DownArrow] = 0x28; // VK_DOWN + io.KeyMap[ImGuiKey_Enter] = 0x0D; // VK_RETURN + io.KeyMap[ImGuiKey_Escape] = 0x1B; // VK_ESCAPE + io.KeyMap[ImGuiKey_Delete] = 0x2E; // VK_DELETE + io.KeyMap[ImGuiKey_Backspace] = 0x08; // VK_BACK + io.KeyMap[ImGuiKey_Space] = 0x20; // VK_SPACE + io.KeyMap[ImGuiKey_A] = 0x41; // VK_A + io.KeyMap[ImGuiKey_C] = 0x43; // VK_C + io.KeyMap[ImGuiKey_V] = 0x56; // VK_V + io.KeyMap[ImGuiKey_X] = 0x58; // VK_X + io.KeyMap[ImGuiKey_Y] = 0x59; // VK_Y + io.KeyMap[ImGuiKey_Z] = 0x5A; // VK_Z + + std::cout << "UIManager initialized with size: " << width << "x" << height << std::endl; + std::cout << "ImGui font atlas created: " << width_atlas << "x" << height_atlas << std::endl; +} + +void UIManager::setStyle(uint32_t index) +{ + selectedStyle = index; + + switch (index) { + case 0: // Vulkan Red (default) + { + ImGuiStyle& style = ImGui::GetStyle(); + style = vulkanStyle; + break; + } + case 1: // Classic + ImGui::StyleColorsClassic(); + break; + case 2: // Dark + ImGui::StyleColorsDark(); + break; + case 3: // Light + ImGui::StyleColorsLight(); + break; + case 4: // Blue theme + { + ImGuiStyle& style = ImGui::GetStyle(); + style = ImGui::GetStyle(); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.0f, 0.3f, 0.8f, 0.6f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.0f, 0.4f, 1.0f, 0.8f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.0f, 0.2f, 0.6f, 0.4f); + style.Colors[ImGuiCol_Header] = ImVec4(0.0f, 0.4f, 1.0f, 0.4f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(0.0f, 1.0f, 0.0f, 1.0f); + break; + } + case 5: // Green theme + { + ImGuiStyle& style = ImGui::GetStyle(); + style = ImGui::GetStyle(); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.0f, 0.6f, 0.2f, 0.6f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.0f, 0.8f, 0.3f, 0.8f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.0f, 0.4f, 0.1f, 0.4f); + style.Colors[ImGuiCol_Header] = ImVec4(0.0f, 0.8f, 0.3f, 0.4f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(1.0f, 1.0f, 0.0f, 1.0f); + break; + } + case 6: // Purple theme + { + ImGuiStyle& style = ImGui::GetStyle(); + style = ImGui::GetStyle(); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.5f, 0.0f, 0.8f, 0.6f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.7f, 0.0f, 1.0f, 0.8f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.3f, 0.0f, 0.6f, 0.4f); + style.Colors[ImGuiCol_Header] = ImVec4(0.7f, 0.0f, 1.0f, 0.4f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(1.0f, 1.0f, 0.0f, 1.0f); + break; + } + } +} + +void UIManager::initResources(VkRenderPass renderPass, VkQueue copyQueue, const std::string& shadersPath, VkFormat colorFormat, VkFormat depthFormat) +{ + std::cout << "UIManager: Initializing full Vulkan resources for ImGui rendering" << std::endl; + + if (!device) { + std::cout << "Error: VulkanDevice not set, cannot initialize ImGui resources" << std::endl; + return; + } + + ImGuiIO& io = ImGui::GetIO(); + + // Create font texture from ImGui font atlas + unsigned char* fontData; + int texWidth, texHeight; + io.Fonts->GetTexDataAsRGBA32(&fontData, &texWidth, &texHeight); + VkDeviceSize uploadSize = texWidth * texHeight * 4 * sizeof(char); + + std::cout << "Creating font texture: " << texWidth << "x" << texHeight << " (" << uploadSize << " bytes)" << std::endl; + + // Create target image for font texture + VkImageCreateInfo imageInfo = {}; + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM; + imageInfo.extent.width = texWidth; + imageInfo.extent.height = texHeight; + imageInfo.extent.depth = 1; + imageInfo.mipLevels = 1; + imageInfo.arrayLayers = 1; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VK_CHECK_RESULT(vkCreateImage(device->logicalDevice, &imageInfo, nullptr, &fontImage)); + + // Allocate memory for the image + VkMemoryRequirements memReqs; + vkGetImageMemoryRequirements(device->logicalDevice, fontImage, &memReqs); + VkMemoryAllocateInfo memAllocInfo = {}; + memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memAllocInfo.allocationSize = memReqs.size; + memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device->logicalDevice, &memAllocInfo, nullptr, &fontMemory)); + VK_CHECK_RESULT(vkBindImageMemory(device->logicalDevice, fontImage, fontMemory, 0)); + + // Create image view + VkImageViewCreateInfo viewInfo = {}; + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.image = fontImage; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.format = VK_FORMAT_R8G8B8A8_UNORM; + viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.subresourceRange.levelCount = 1; + viewInfo.subresourceRange.layerCount = 1; + VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewInfo, nullptr, &fontView)); + + // Upload font data using staging buffer + vks::Buffer stagingBuffer; + VK_CHECK_RESULT(device->createBuffer( + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &stagingBuffer, + uploadSize)); + + stagingBuffer.map(); + memcpy(stagingBuffer.mapped, fontData, uploadSize); + stagingBuffer.unmap(); + + // Copy buffer to image + VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + + // Transition image layout for transfer + VkImageMemoryBarrier imageMemoryBarrier = {}; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.srcAccessMask = 0; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.image = fontImage; + imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); + + // Copy buffer to image + VkBufferImageCopy bufferCopyRegion = {}; + bufferCopyRegion.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; + bufferCopyRegion.imageExtent = { static_cast(texWidth), static_cast(texHeight), 1 }; + vkCmdCopyBufferToImage(copyCmd, stagingBuffer.buffer, fontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion); + + // Transition to shader read layout + imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); + + device->flushCommandBuffer(copyCmd, copyQueue); + stagingBuffer.destroy(); + + // Create sampler + VkSamplerCreateInfo samplerInfo = {}; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + VK_CHECK_RESULT(vkCreateSampler(device->logicalDevice, &samplerInfo, nullptr, &sampler)); + + // Create descriptor pool + std::vector poolSizes = { + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 } + }; + VkDescriptorPoolCreateInfo descriptorPoolInfo = {}; + descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptorPoolInfo.poolSizeCount = static_cast(poolSizes.size()); + descriptorPoolInfo.pPoolSizes = poolSizes.data(); + descriptorPoolInfo.maxSets = 2; + VK_CHECK_RESULT(vkCreateDescriptorPool(device->logicalDevice, &descriptorPoolInfo, nullptr, &descriptorPool)); + + // Create descriptor set layout + VkDescriptorSetLayoutBinding setLayoutBinding = {}; + setLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + setLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + setLayoutBinding.binding = 0; + setLayoutBinding.descriptorCount = 1; + VkDescriptorSetLayoutCreateInfo descriptorLayout = {}; + descriptorLayout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptorLayout.bindingCount = 1; + descriptorLayout.pBindings = &setLayoutBinding; + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device->logicalDevice, &descriptorLayout, nullptr, &descriptorSetLayout)); + + // Create descriptor set + VkDescriptorSetAllocateInfo allocInfo = {}; + allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocInfo.descriptorPool = descriptorPool; + allocInfo.descriptorSetCount = 1; + allocInfo.pSetLayouts = &descriptorSetLayout; + VK_CHECK_RESULT(vkAllocateDescriptorSets(device->logicalDevice, &allocInfo, &descriptorSet)); + + // Update descriptor set + VkDescriptorImageInfo fontDescriptor = {}; + fontDescriptor.sampler = sampler; + fontDescriptor.imageView = fontView; + fontDescriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet writeDescriptorSet = {}; + writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeDescriptorSet.dstSet = descriptorSet; + writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writeDescriptorSet.dstBinding = 0; + writeDescriptorSet.pImageInfo = &fontDescriptor; + writeDescriptorSet.descriptorCount = 1; + vkUpdateDescriptorSets(device->logicalDevice, 1, &writeDescriptorSet, 0, nullptr); + + // Store texture ID in ImGui + io.Fonts->TexID = (ImTextureID)(intptr_t)fontImage; + + // Create pipeline layout with push constants + VkPushConstantRange pushConstantRange = {}; + pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + pushConstantRange.offset = 0; + pushConstantRange.size = sizeof(PushConstBlock); + + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {}; + pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutCreateInfo.setLayoutCount = 1; + pipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayout; + pipelineLayoutCreateInfo.pushConstantRangeCount = 1; + pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; + VK_CHECK_RESULT(vkCreatePipelineLayout(device->logicalDevice, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + + // Create graphics pipeline for ImGui rendering + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {}; + inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + inputAssemblyState.flags = 0; + inputAssemblyState.primitiveRestartEnable = VK_FALSE; + + VkPipelineRasterizationStateCreateInfo rasterizationState = {}; + rasterizationState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizationState.polygonMode = VK_POLYGON_MODE_FILL; + rasterizationState.cullMode = VK_CULL_MODE_NONE; + rasterizationState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterizationState.flags = 0; + rasterizationState.depthClampEnable = VK_FALSE; + rasterizationState.lineWidth = 1.0f; + + // Enable blending for UI transparency + VkPipelineColorBlendAttachmentState blendAttachmentState = {}; + blendAttachmentState.blendEnable = VK_TRUE; + blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; + blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; + + VkPipelineColorBlendStateCreateInfo colorBlendState = {}; + colorBlendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlendState.attachmentCount = 1; + colorBlendState.pAttachments = &blendAttachmentState; + + VkPipelineDepthStencilStateCreateInfo depthStencilState = {}; + depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencilState.depthTestEnable = VK_FALSE; + depthStencilState.depthWriteEnable = VK_FALSE; + depthStencilState.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + depthStencilState.back.compareOp = VK_COMPARE_OP_ALWAYS; + + VkPipelineViewportStateCreateInfo viewportState = {}; + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.scissorCount = 1; + viewportState.flags = 0; + + VkPipelineMultisampleStateCreateInfo multisampleState = {}; + multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + multisampleState.flags = 0; + + std::vector dynamicStateEnables = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + VkPipelineDynamicStateCreateInfo dynamicState = {}; + dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamicState.dynamicStateCount = static_cast(dynamicStateEnables.size()); + dynamicState.pDynamicStates = dynamicStateEnables.data(); + dynamicState.flags = 0; + + // Vertex input for ImGui (ImDrawVert format) + std::vector vertexInputBindings = { + { 0, sizeof(ImDrawVert), VK_VERTEX_INPUT_RATE_VERTEX } + }; + std::vector vertexInputAttributes = { + { 0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(ImDrawVert, pos) }, // Position + { 1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(ImDrawVert, uv) }, // UV + { 2, 0, VK_FORMAT_R8G8B8A8_UNORM, offsetof(ImDrawVert, col) } // Color + }; + VkPipelineVertexInputStateCreateInfo vertexInputState = {}; + vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); + vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); + vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); + vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); + + // Load shaders + std::array shaderStages; + shaderStages[0] = application->loadShader(shadersPath + "imgui/ui.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = application->loadShader(shadersPath + "imgui/ui.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + + // Create pipeline for dynamic rendering (no render pass) + VkGraphicsPipelineCreateInfo pipelineCreateInfo = {}; + pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineCreateInfo.layout = pipelineLayout; + pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; + pipelineCreateInfo.pRasterizationState = &rasterizationState; + pipelineCreateInfo.pColorBlendState = &colorBlendState; + pipelineCreateInfo.pMultisampleState = &multisampleState; + pipelineCreateInfo.pViewportState = &viewportState; + pipelineCreateInfo.pDepthStencilState = &depthStencilState; + pipelineCreateInfo.pDynamicState = &dynamicState; + pipelineCreateInfo.pVertexInputState = &vertexInputState; + pipelineCreateInfo.stageCount = static_cast(shaderStages.size()); + pipelineCreateInfo.pStages = shaderStages.data(); + + // Dynamic rendering create info (no render pass needed) + VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo = {}; + if (colorFormat != VK_FORMAT_UNDEFINED) { + pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; + pipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipelineRenderingCreateInfo.pColorAttachmentFormats = &colorFormat; + pipelineRenderingCreateInfo.depthAttachmentFormat = depthFormat; + pipelineRenderingCreateInfo.stencilAttachmentFormat = depthFormat; + pipelineCreateInfo.pNext = &pipelineRenderingCreateInfo; + } + + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device->logicalDevice, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &pipeline)); + + std::cout << "UIManager: Full Vulkan resources initialized successfully" << std::endl; +} + +void UIManager::newFrame(Application *app, bool updateFrameGraph) +{ + std::cout << "UIManager::newFrame() - START" << std::endl; + + // Update ImGui IO with frame timing information + ImGuiIO& io = ImGui::GetIO(); + io.DeltaTime = app->frameTimer; // Use frame timer from VulkanExampleBase + + std::cout << "Calling ImGui::NewFrame()" << std::endl; + ImGui::NewFrame(); + + std::cout << "UIManager::newFrame() - uiSettings: " << uiSettings << ", sceneManager: " << sceneManager << std::endl; + + if (!uiSettings || !sceneManager) { + std::cout << "UIManager: Missing settings or scene manager - rendering placeholder UI" << std::endl; + ImGui::Text("UI System Initialized"); + ImGui::Text("Settings and Scene Manager not yet connected"); + std::cout << "Calling ImGui::Render() for placeholder" << std::endl; + ImGui::Render(); // Generate draw buffers even for placeholder UI + std::cout << "UIManager::newFrame() - END (placeholder)" << std::endl; + return; + } + + // Render all UI panels + renderMainMenuBar(); + renderDebugPanel(); + + if (uiSettings->showSceneHierarchyPanel) { + renderSceneHierarchyPanel(); + } + + if (uiSettings->showInspectorPanel) { + renderInspectorPanel(); + } + + if (uiSettings->showViewportPanel) { + renderViewportPanel(); + } + + if (uiSettings->showAssetBrowserPanel) { + renderAssetBrowserPanel(); + } + + if (uiSettings->showConsolePanel) { + renderConsolePanel(); + } + + // Generate ImGui draw buffers + std::cout << "Calling ImGui::Render() at end" << std::endl; + ImGui::Render(); +} + +void UIManager::updateBuffers() +{ + ImDrawData* imDrawData = ImGui::GetDrawData(); + + if (!imDrawData || !device) { + return; + } + + // Calculate buffer sizes + VkDeviceSize vertexBufferSize = imDrawData->TotalVtxCount * sizeof(ImDrawVert); + VkDeviceSize indexBufferSize = imDrawData->TotalIdxCount * sizeof(ImDrawIdx); + + if ((vertexBufferSize == 0) || (indexBufferSize == 0)) { + return; + } + + // Update vertex buffer + if ((vertexBuffer.buffer == VK_NULL_HANDLE) || (vertexCount != imDrawData->TotalVtxCount)) { + if (vertexBuffer.buffer != VK_NULL_HANDLE) { + vertexBuffer.destroy(); + } + VK_CHECK_RESULT(device->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &vertexBuffer, vertexBufferSize)); + vertexCount = imDrawData->TotalVtxCount; + } + + // Update index buffer + if ((indexBuffer.buffer == VK_NULL_HANDLE) || (indexCount != imDrawData->TotalIdxCount)) { + if (indexBuffer.buffer != VK_NULL_HANDLE) { + indexBuffer.destroy(); + } + VK_CHECK_RESULT(device->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &indexBuffer, indexBufferSize)); + indexCount = imDrawData->TotalIdxCount; + } + + // Copy vertex data + vertexBuffer.map(); + ImDrawVert* vtxDst = (ImDrawVert*)vertexBuffer.mapped; + for (int n = 0; n < imDrawData->CmdListsCount; n++) { + const ImDrawList* cmd_list = imDrawData->CmdLists[n]; + memcpy(vtxDst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + vtxDst += cmd_list->VtxBuffer.Size; + } + vertexBuffer.unmap(); + + // Copy index data + indexBuffer.map(); + ImDrawIdx* idxDst = (ImDrawIdx*)indexBuffer.mapped; + for (int n = 0; n < imDrawData->CmdListsCount; n++) { + const ImDrawList* cmd_list = imDrawData->CmdLists[n]; + memcpy(idxDst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + idxDst += cmd_list->IdxBuffer.Size; + } + indexBuffer.unmap(); +} + +void UIManager::drawFrame(VkCommandBuffer commandBuffer) +{ + ImDrawData* imDrawData = ImGui::GetDrawData(); + + if (!imDrawData || imDrawData->CmdListsCount == 0 || !device) { + return; + } + + // Bind the ImGui pipeline + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + + // Set viewport + VkViewport viewport = {}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = imDrawData->DisplaySize.x; + viewport.height = imDrawData->DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + + // UI scale and translate via push constants + pushConstBlock.scale = glm::vec2(2.0f / imDrawData->DisplaySize.x, 2.0f / imDrawData->DisplaySize.y); + pushConstBlock.translate = glm::vec2(-1.0f); + vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock); + + // Bind vertex and index buffers + VkDeviceSize offsets[1] = { 0 }; + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer.buffer, offsets); + vkCmdBindIndexBuffer(commandBuffer, indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16); + + // Render command lists + int32_t vertexOffset = 0; + int32_t indexOffset = 0; + + for (int32_t i = 0; i < imDrawData->CmdListsCount; i++) { + const ImDrawList* cmd_list = imDrawData->CmdLists[i]; + + for (int32_t j = 0; j < cmd_list->CmdBuffer.Size; j++) { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[j]; + + // Set scissor rectangle + VkRect2D scissorRect; + scissorRect.offset.x = glm::max((int32_t)(pcmd->ClipRect.x), 0); + scissorRect.offset.y = glm::max((int32_t)(pcmd->ClipRect.y), 0); + scissorRect.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissorRect.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y); + vkCmdSetScissor(commandBuffer, 0, 1, &scissorRect); + + // Draw + vkCmdDrawIndexed(commandBuffer, pcmd->ElemCount, 1, indexOffset, vertexOffset, 0); + indexOffset += pcmd->ElemCount; + } + vertexOffset += cmd_list->VtxBuffer.Size; + } +} + +void UIManager::resize(uint32_t width, uint32_t height) +{ + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2(static_cast(width), static_cast(height)); + std::cout << "UIManager resized to: " << width << "x" << height << std::endl; +} + +// === Panel Rendering Methods (Placeholder Implementations) === + +void UIManager::renderMainMenuBar() +{ + if (ImGui::BeginMainMenuBar()) { + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("New Scene", "Ctrl+N")) { + sceneManager->clearScene(); + } + if (ImGui::MenuItem("Open Scene", "Ctrl+O")) { + std::cout << "TODO: Implement scene loading" << std::endl; + } + if (ImGui::MenuItem("Save Scene", "Ctrl+S")) { + std::cout << "TODO: Implement scene saving" << std::endl; + } + ImGui::Separator(); + if (ImGui::MenuItem("Exit", "Alt+F4")) { + std::cout << "Exit requested" << std::endl; + } + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Preferences")) { + if (ImGui::BeginMenu("UI Theme")) { + if (ImGui::MenuItem("Vulkan Red", nullptr, selectedStyle == 0)) { setStyle(0); } + if (ImGui::MenuItem("Classic", nullptr, selectedStyle == 1)) { setStyle(1); } + if (ImGui::MenuItem("Dark", nullptr, selectedStyle == 2)) { setStyle(2); } + if (ImGui::MenuItem("Light", nullptr, selectedStyle == 3)) { setStyle(3); } + if (ImGui::MenuItem("Blue", nullptr, selectedStyle == 4)) { setStyle(4); } + if (ImGui::MenuItem("Green", nullptr, selectedStyle == 5)) { setStyle(5); } + if (ImGui::MenuItem("Purple", nullptr, selectedStyle == 6)) { setStyle(6); } + ImGui::EndMenu(); + } + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Windows")) { + ImGui::MenuItem("Scene Hierarchy", nullptr, &uiSettings->showSceneHierarchyPanel); + ImGui::MenuItem("Inspector", nullptr, &uiSettings->showInspectorPanel); + ImGui::MenuItem("Viewport", nullptr, &uiSettings->showViewportPanel); + ImGui::MenuItem("Asset Browser", nullptr, &uiSettings->showAssetBrowserPanel); + ImGui::MenuItem("Console", nullptr, &uiSettings->showConsolePanel); + ImGui::Separator(); + if (ImGui::MenuItem("Show All Panels")) { + uiSettings->showSceneHierarchyPanel = true; + uiSettings->showInspectorPanel = true; + uiSettings->showViewportPanel = true; + uiSettings->showAssetBrowserPanel = true; + uiSettings->showConsolePanel = true; + } + if (ImGui::MenuItem("Hide All Panels")) { + uiSettings->showSceneHierarchyPanel = false; + uiSettings->showInspectorPanel = false; + uiSettings->showViewportPanel = false; + uiSettings->showAssetBrowserPanel = false; + uiSettings->showConsolePanel = false; + } + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Help")) { + if (ImGui::MenuItem("About")) { + std::cout << "TODO: Show about dialog" << std::endl; + } + ImGui::EndMenu(); + } + + ImGui::EndMainMenuBar(); + } +} + +void UIManager::renderDebugPanel() +{ + ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(300, 300), ImGuiCond_Always); + ImGui::Begin("Debug Info"); + + ImGui::Text("Procedural 3D Engine"); + ImGui::Text("UI System Active"); + ImGui::Separator(); + + ImGui::Text("Orbit Camera Controls:"); + ImGui::BulletText("F - Focus on selection"); + ImGui::BulletText("Alt+LMB - Orbit"); + ImGui::BulletText("Alt+MMB - Pan"); + ImGui::BulletText("Alt+RMB - Zoom"); + ImGui::BulletText("Mouse Wheel - Zoom"); + + ImGui::End(); +} + +void UIManager::renderSceneHierarchyPanel() +{ + ImGui::SetNextWindowPos(ImVec2(20, 360), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(300, 400), ImGuiCond_FirstUseEver); + ImGui::Begin("Scene Hierarchy", &uiSettings->showSceneHierarchyPanel); + + // Header with object count + ImGui::Text("Scene Objects: %d", sceneManager->getObjectCount()); + ImGui::Separator(); + + // Render simple object list + if (sceneManager->getObjectCount() == 0) { + ImGui::Spacing(); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Scene is empty"); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Add objects from Asset Browser"); + } else { + const auto& objects = sceneManager->getObjects(); + for (int i = 0; i < objects.size(); i++) { + const auto& obj = objects[i]; + bool isSelected = (sceneManager->getSelectedIndex() == i); + + // Object icon based on type + const char* icon = "[P]"; // Default procedural icon + if (obj.type == "Model") icon = "[M]"; + + // Visibility toggle (use object name as unique ImGui ID) + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushID(obj.name.c_str()); // Use object name for unique ImGui ID + if (ImGui::SmallButton(obj.visible ? "V" : "H")) { + // Toggle visibility (note: const_cast needed for modification) + const_cast(obj).visible = !obj.visible; + } + ImGui::PopID(); + ImGui::PopStyleColor(); + ImGui::SameLine(); + + // Selectable object name with highlighting for selected objects + if (isSelected) { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.2f, 1.0f)); // Gold color for selected + } + if (ImGui::Selectable((std::string(icon) + " " + obj.name).c_str(), isSelected)) { + sceneManager->setSelectedObject(i); + std::cout << "Selected object: " << obj.name << std::endl; + } + if (isSelected) { + ImGui::PopStyleColor(); + } + + // Right-click context menu + if (ImGui::BeginPopupContextItem()) { + if (ImGui::MenuItem("Delete")) { + sceneManager->removeObject(i); + std::cout << "Deleted object: " << obj.name << std::endl; + } + ImGui::EndPopup(); + } + } + } + + ImGui::End(); +} + +void UIManager::renderInspectorPanel() +{ + ImGui::SetNextWindowPos(ImVec2(1180, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(300, 700), ImGuiCond_FirstUseEver); + ImGui::Begin("Inspector", &uiSettings->showInspectorPanel); + + ImGui::Text("Object Properties:"); + ImGui::Separator(); + + if (sceneManager->getSelectedIndex() >= 0 && sceneManager->getSelectedIndex() < sceneManager->getObjects().size()) { + auto& selectedObj = sceneManager->getObjects()[sceneManager->getSelectedIndex()]; // Non-const for editing + + // Basic object info + ImGui::Text("Name: %s", selectedObj.name.c_str()); + ImGui::Text("Type: %s", selectedObj.type.c_str()); + ImGui::Text("Subtype: %s", selectedObj.subtype.c_str()); + ImGui::Separator(); + + // Visibility toggle + if (ImGui::Checkbox("Visible", &selectedObj.visible)) { + std::cout << "Visibility toggled for " << selectedObj.name << std::endl; + } + ImGui::Separator(); + + // Transform Section (collapsible like backup reference) + if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) { + // Position Vector3 control + float pos[3] = { selectedObj.position.x, selectedObj.position.y, selectedObj.position.z }; + if (ImGui::DragFloat3("Position", pos, 0.1f)) { + selectedObj.position = glm::vec3(pos[0], pos[1], pos[2]); + } + ImGui::SameLine(); + if (ImGui::SmallButton("Reset##pos")) { + selectedObj.position = glm::vec3(0.0f, 0.0f, 0.0f); + } + + // Rotation Vector3 control (degrees) + float rot[3] = { selectedObj.rotation.x, selectedObj.rotation.y, selectedObj.rotation.z }; + if (ImGui::DragFloat3("Rotation", rot, 1.0f, -360.0f, 360.0f)) { + selectedObj.rotation = glm::vec3(rot[0], rot[1], rot[2]); + } + ImGui::SameLine(); + if (ImGui::SmallButton("Reset##rot")) { + selectedObj.rotation = glm::vec3(0.0f, 0.0f, 0.0f); + } + + // Scale Vector3 control + float scale[3] = { selectedObj.scale.x, selectedObj.scale.y, selectedObj.scale.z }; + if (ImGui::DragFloat3("Scale", scale, 0.01f, 0.01f, 10.0f)) { + selectedObj.scale = glm::vec3(scale[0], scale[1], scale[2]); + } + ImGui::SameLine(); + if (ImGui::SmallButton("Reset##scale")) { + selectedObj.scale = glm::vec3(1.0f, 1.0f, 1.0f); // Default scale is 1.0 + } + + // Transform utilities + ImGui::Spacing(); + if (ImGui::Button("Reset All Transform")) { + selectedObj.position = glm::vec3(0.0f, 0.0f, 0.0f); + selectedObj.rotation = glm::vec3(0.0f, 0.0f, 0.0f); + selectedObj.scale = glm::vec3(1.0f, 1.0f, 1.0f); + } + } + + // Procedural parameters (only for Procedural objects) + if (selectedObj.type == "Procedural") { + bool parametersChanged = false; + + if (selectedObj.subtype == "Cube") { + ImGui::Text("Cube Parameters:"); + ImGui::Separator(); + + if (ImGui::DragFloat("Width", &selectedObj.proceduralParams.cubeWidth, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::DragFloat("Height", &selectedObj.proceduralParams.cubeHeight, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::DragFloat("Depth", &selectedObj.proceduralParams.cubeDepth, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::SliderInt("Subdivisions", &selectedObj.proceduralParams.cubeSubdivisions, 1, 10)) { + parametersChanged = true; + } + + if (ImGui::Button("Reset Cube Parameters")) { + selectedObj.proceduralParams.cubeWidth = 2.0f; + selectedObj.proceduralParams.cubeHeight = 2.0f; + selectedObj.proceduralParams.cubeDepth = 2.0f; + selectedObj.proceduralParams.cubeSubdivisions = 1; + parametersChanged = true; + } + + } else if (selectedObj.subtype == "Sphere") { + ImGui::Text("Sphere Parameters:"); + ImGui::Separator(); + + if (ImGui::DragFloat("Radius", &selectedObj.proceduralParams.sphereRadius, 0.05f, 0.1f, 5.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::SliderInt("Segments", &selectedObj.proceduralParams.sphereSegments, 4, 64)) { + parametersChanged = true; + } + + if (ImGui::Button("Reset Sphere Parameters")) { + selectedObj.proceduralParams.sphereRadius = 1.0f; + selectedObj.proceduralParams.sphereSegments = 16; + parametersChanged = true; + } + + } else if (selectedObj.subtype == "Cylinder") { + ImGui::Text("Cylinder Parameters:"); + ImGui::Separator(); + + if (ImGui::DragFloat("Radius", &selectedObj.proceduralParams.cylinderRadius, 0.05f, 0.1f, 5.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::DragFloat("Height", &selectedObj.proceduralParams.cylinderHeight, 0.1f, 0.1f, 10.0f, "%.2f")) { + parametersChanged = true; + } + if (ImGui::SliderInt("Segments", &selectedObj.proceduralParams.cylinderSegments, 4, 64)) { + parametersChanged = true; + } + + if (ImGui::Button("Reset Cylinder Parameters")) { + selectedObj.proceduralParams.cylinderRadius = 1.0f; + selectedObj.proceduralParams.cylinderHeight = 2.0f; + selectedObj.proceduralParams.cylinderSegments = 16; + parametersChanged = true; + } + } + + // If parameters changed, regenerate geometry + if (parametersChanged) { + selectedObj.regenerateGeometry(); + std::cout << "Regenerated geometry for " << selectedObj.name << std::endl; + } + } + } else { + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "No object selected"); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Select an object to edit properties"); + } + + ImGui::End(); +} + +void UIManager::renderViewportPanel() +{ + ImGui::SetNextWindowPos(ImVec2(660, 350), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(320, 280), ImGuiCond_FirstUseEver); + ImGui::Begin("Viewport", &uiSettings->showViewportPanel); + + ImGui::Text("3D Viewport Settings:"); + ImGui::Separator(); + + if (ImGui::CollapsingHeader("Render Mode", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Checkbox("Show Grid", &uiSettings->showGrid); + ImGui::DragFloat("Grid Size", &uiSettings->gridSize, 0.5f, 1.0f, 50.0f); + ImGui::SliderInt("Grid Divisions", &uiSettings->gridDivisions, 2, 50); + } + + if (ImGui::CollapsingHeader("Lighting")) { + ImGui::Checkbox("Animate light", &uiSettings->animateLight); + ImGui::SliderFloat("Light speed", &uiSettings->lightSpeed, 0.1f, 1.0f); + } + + ImGui::End(); +} + +void UIManager::renderAssetBrowserPanel() +{ + ImGui::SetNextWindowPos(ImVec2(20, 780), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(600, 220), ImGuiCond_FirstUseEver); + ImGui::Begin("Asset Browser", &uiSettings->showAssetBrowserPanel); + + ImGui::Text("Project Assets:"); + ImGui::Separator(); + + if (ImGui::CollapsingHeader("Procedural Shapes", ImGuiTreeNodeFlags_DefaultOpen)) { + if (ImGui::Button("Add Cube")) { + std::cout << "DEBUG: Add Cube button clicked!" << std::endl; + if (sceneManager) { + sceneManager->addObject("Cube", "Cube"); + std::cout << "Added Cube to scene - object count now: " << sceneManager->getObjectCount() << std::endl; + } else { + std::cout << "ERROR: sceneManager is null!" << std::endl; + } + } + ImGui::SameLine(); + if (ImGui::Button("Add Sphere")) { + std::cout << "DEBUG: Add Sphere button clicked!" << std::endl; + if (sceneManager) { + sceneManager->addObject("Sphere", "Sphere"); + std::cout << "Added Sphere to scene - object count now: " << sceneManager->getObjectCount() << std::endl; + } else { + std::cout << "ERROR: sceneManager is null!" << std::endl; + } + } + ImGui::SameLine(); + if (ImGui::Button("Add Cylinder")) { + std::cout << "DEBUG: Add Cylinder button clicked!" << std::endl; + if (sceneManager) { + sceneManager->addObject("Cylinder", "Cylinder"); + std::cout << "Added Cylinder to scene - object count now: " << sceneManager->getObjectCount() << std::endl; + } else { + std::cout << "ERROR: sceneManager is null!" << std::endl; + } + } + + if (ImGui::Button("Add Cone")) { + std::cout << "DEBUG: Add Cone button clicked!" << std::endl; + if (sceneManager) { + sceneManager->addObject("Cone", "Cone"); + std::cout << "Added Cone to scene - object count now: " << sceneManager->getObjectCount() << std::endl; + } else { + std::cout << "ERROR: sceneManager is null!" << std::endl; + } + } + ImGui::SameLine(); + if (ImGui::Button("Add Plane")) { + std::cout << "DEBUG: Add Plane button clicked!" << std::endl; + if (sceneManager) { + sceneManager->addObject("Plane", "Plane"); + std::cout << "Added Plane to scene - object count now: " << sceneManager->getObjectCount() << std::endl; + } else { + std::cout << "ERROR: sceneManager is null!" << std::endl; + } + } + ImGui::SameLine(); + if (ImGui::Button("Add Torus")) { + std::cout << "DEBUG: Add Torus button clicked!" << std::endl; + if (sceneManager) { + sceneManager->addObject("Torus", "Torus"); + std::cout << "Added Torus to scene - object count now: " << sceneManager->getObjectCount() << std::endl; + } else { + std::cout << "ERROR: sceneManager is null!" << std::endl; + } + } + } + + if (ImGui::CollapsingHeader("Models")) { + ImGui::Text("• glTF Model Loading (TODO)"); + } + + if (ImGui::CollapsingHeader("Materials")) { + ImGui::Text("• Default Vulkan Materials"); + } + + ImGui::End(); +} + +void UIManager::renderConsolePanel() +{ + ImGui::SetNextWindowPos(ImVec2(640, 780), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(840, 200), ImGuiCond_FirstUseEver); + ImGui::Begin("Console", &uiSettings->showConsolePanel); + + ImGui::Text("System Console:"); + ImGui::Separator(); + ImGui::Text("[INFO] ProceduralEngine - Vulkan Renderer initialized"); + ImGui::Text("[INFO] Scene loaded successfully - Ready for procedural generation"); + ImGui::Separator(); + + static char inputBuf[256] = ""; + if (ImGui::InputText("Command", inputBuf, sizeof(inputBuf), ImGuiInputTextFlags_EnterReturnsTrue)) { + std::cout << "Console command: " << inputBuf << std::endl; + inputBuf[0] = '\0'; + } + + ImGui::End(); +} \ No newline at end of file diff --git a/src/ui/UIManager.h b/src/ui/UIManager.h new file mode 100644 index 00000000..74ef350d --- /dev/null +++ b/src/ui/UIManager.h @@ -0,0 +1,102 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#pragma once + +#include "foundation/vulkanexamplebase.h" +#include "device/VulkanDevice.h" +#include "memory/VulkanBuffer.h" +#include "UISettings.h" +#include "../scene/SceneManager.h" +#include +#include +#include + +// Forward declarations +class Application; + +// Enhanced ImGUI class for managing the entire UI system +class UIManager { +private: + // Vulkan resources for rendering the UI + VkSampler sampler; + VkImage fontImage = VK_NULL_HANDLE; + VkImageView fontView = VK_NULL_HANDLE; + VkDeviceMemory fontMemory = VK_NULL_HANDLE; + VkDescriptorPool descriptorPool; + VkDescriptorSetLayout descriptorSetLayout; + VkDescriptorSet descriptorSet; + VkPipelineLayout pipelineLayout; + VkPipeline pipeline; + + vks::VulkanDevice *device; + Application *application; + + vks::Buffer vertexBuffer; + vks::Buffer indexBuffer; + int32_t vertexCount = 0; + int32_t indexCount = 0; + + // UI styling + ImGuiStyle vulkanStyle; + int selectedStyle = 0; + + // UI state + UISettings* uiSettings; + SceneManager* sceneManager; + +public: + // Push constants for UI rendering + struct PushConstBlock { + glm::vec2 scale; + glm::vec2 translate; + } pushConstBlock; + + UIManager(Application *app); + ~UIManager(); + + // Core UI management methods + void init(float width, float height); + void initResources(VkRenderPass renderPass, VkQueue copyQueue, const std::string& shadersPath, VkFormat colorFormat = VK_FORMAT_UNDEFINED, VkFormat depthFormat = VK_FORMAT_UNDEFINED); + void newFrame(Application *app, bool updateFrameGraph); + void updateBuffers(); + void drawFrame(VkCommandBuffer commandBuffer); + void resize(uint32_t width, uint32_t height); + + // UI styling + void setStyle(uint32_t index); + + // Settings access + void setUISettings(UISettings* settings) { + std::cout << "UIManager::setUISettings() called with pointer: " << settings << std::endl; + uiSettings = settings; + } + void setSceneManager(SceneManager* manager) { + std::cout << "UIManager::setSceneManager() called with pointer: " << manager << std::endl; + sceneManager = manager; + } + void setDevice(vks::VulkanDevice* dev) { + std::cout << "UIManager::setDevice() called with pointer: " << dev << std::endl; + device = dev; + } + +private: + // Internal rendering methods + void prepareResources(); + void preparePipeline(VkRenderPass renderPass, VkFormat colorFormat, VkFormat depthFormat); + void updateVertexAndIndexBuffer(); + + // UI panel rendering (will be extracted to separate files later) + void renderMainMenuBar(); + void renderDebugPanel(); + void renderSceneHierarchyPanel(); + void renderInspectorPanel(); + void renderViewportPanel(); + void renderAssetBrowserPanel(); + void renderConsolePanel(); +}; \ No newline at end of file diff --git a/src/ui/UISettings.h b/src/ui/UISettings.h new file mode 100644 index 00000000..07bd60da --- /dev/null +++ b/src/ui/UISettings.h @@ -0,0 +1,38 @@ +/* + * Procedural 3D Engine + * Copyright (c) 2025 Your Project + * + * This software is licensed under the MIT License. + * See LICENSE.md for full license information. + */ + +#pragma once + +#include + +// UI Settings structure for managing editor interface state +struct UISettings { + // Model and background display toggles + bool displayModels = false; + bool displayBackground = false; + bool animateLight = false; + float lightSpeed = 0.25f; + + // Performance monitoring + std::array frameTimes{}; + float frameTimeMin = 9999.0f; + float frameTimeMax = 0.0f; + float lightTimer = 0.0f; + + // Grid settings + bool showGrid = true; + float gridSize = 10.0f; + int gridDivisions = 10; + + // Panel visibility settings (for Windows menu) + bool showViewportPanel = true; + bool showInspectorPanel = true; + bool showSceneHierarchyPanel = true; + bool showAssetBrowserPanel = true; + bool showConsolePanel = false; // Hidden by default +}; \ No newline at end of file