init
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
Generated
+2774
File diff suppressed because it is too large
Load Diff
+32
@@ -0,0 +1,32 @@
|
|||||||
|
[package]
|
||||||
|
name = "erroccfisumreg"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
vulkano = "0.32"
|
||||||
|
# Provides the `shader!` macro that is used to generate code for using shaders.
|
||||||
|
vulkano-shaders = "0.32"
|
||||||
|
# The Vulkan library doesn't provide any functionality to create and handle windows, as
|
||||||
|
# this would be out of scope. In order to open a window, we are going to use the `winit` crate.
|
||||||
|
winit = "0.27"
|
||||||
|
# The `vulkano_win` crate is the link between `vulkano` and `winit`. Vulkano doesn't know about winit,
|
||||||
|
# and winit doesn't know about vulkano, so import a crate that will provide a link between the two.
|
||||||
|
vulkano-win = "0.32"
|
||||||
|
vulkano-util = "0.32"
|
||||||
|
|
||||||
|
obj = "0.10"
|
||||||
|
bytemuck = { version = "1.13", features = [
|
||||||
|
"derive",
|
||||||
|
"extern_crate_std",
|
||||||
|
"min_const_generics",
|
||||||
|
] }
|
||||||
|
|
||||||
|
cgmath = "0.18"
|
||||||
|
|
||||||
|
rodio = "0.16"
|
||||||
|
|
||||||
|
egui = "0.20"
|
||||||
|
egui_winit_vulkano = "0.22"
|
||||||
+140215
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,251 @@
|
|||||||
|
// Modifications Copyright © 2021. Advanced Micro Devices, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (c) 2016, Intel Corporation
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
|
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is 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 Software.
|
||||||
|
// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// File changes (yyyy-mm-dd)
|
||||||
|
// 2016-09-07: filip.strugar@intel.com: first commit
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/*! \file */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uint8_t FFX_CACAO_Bool;
|
||||||
|
static const FFX_CACAO_Bool FFX_CACAO_TRUE = 1;
|
||||||
|
static const FFX_CACAO_Bool FFX_CACAO_FALSE = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The quality levels that FidelityFX CACAO can generate SSAO at. This affects the number of samples taken for generating SSAO.
|
||||||
|
*/
|
||||||
|
typedef enum FFX_CACAO_Quality {
|
||||||
|
FFX_CACAO_QUALITY_LOWEST = 0,
|
||||||
|
FFX_CACAO_QUALITY_LOW = 1,
|
||||||
|
FFX_CACAO_QUALITY_MEDIUM = 2,
|
||||||
|
FFX_CACAO_QUALITY_HIGH = 3,
|
||||||
|
FFX_CACAO_QUALITY_HIGHEST = 4,
|
||||||
|
} FFX_CACAO_Quality;
|
||||||
|
|
||||||
|
/**
|
||||||
|
A structure representing a 4x4 matrix of floats. The matrix is stored in row major order in memory.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_Matrix4x4 {
|
||||||
|
float elements[4][4];
|
||||||
|
} FFX_CACAO_Matrix4x4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
A structure for the settings used by FidelityFX CACAO. These settings may be updated with each draw call.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_Settings {
|
||||||
|
float radius; ///< [0.0, ~ ] World (view) space size of the occlusion sphere.
|
||||||
|
float shadowMultiplier; ///< [0.0, 5.0] Effect strength linear multiplier.
|
||||||
|
float shadowPower; ///< [0.5, 5.0] Effect strength pow modifier.
|
||||||
|
float shadowClamp; ///< [0.0, 1.0] Effect max limit (applied after multiplier but before blur).
|
||||||
|
float horizonAngleThreshold; ///< [0.0, 0.2] Limits self-shadowing (makes the sampling area less of a hemisphere, more of a spherical cone, to avoid self-shadowing and various artifacts due to low tessellation and depth buffer imprecision, etc.).
|
||||||
|
float fadeOutFrom; ///< [0.0, ~ ] Distance to start fading out the effect.
|
||||||
|
float fadeOutTo; ///< [0.0, ~ ] Distance at which the effect is faded out.
|
||||||
|
FFX_CACAO_Quality qualityLevel; ///< Effect quality, affects number of taps etc.
|
||||||
|
float adaptiveQualityLimit; ///< [0.0, 1.0] (only for quality level FFX_CACAO_QUALITY_HIGHEST).
|
||||||
|
uint32_t blurPassCount; ///< [ 0, 8] Number of edge-sensitive smart blur passes to apply.
|
||||||
|
float sharpness; ///< [0.0, 1.0] (How much to bleed over edges; 1: not at all, 0.5: half-half; 0.0: completely ignore edges).
|
||||||
|
float temporalSupersamplingAngleOffset; ///< [0.0, PI] Used to rotate sampling kernel; If using temporal AA / supersampling, suggested to rotate by ( (frame%3)/3.0*PI ) or similar. Kernel is already symmetrical, which is why we use PI and not 2*PI.
|
||||||
|
float temporalSupersamplingRadiusOffset; ///< [0.0, 2.0] Used to scale sampling kernel; If using temporal AA / supersampling, suggested to scale by ( 1.0f + (((frame%3)-1.0)/3.0)*0.1 ) or similar.
|
||||||
|
float detailShadowStrength; ///< [0.0, 5.0] Used for high-res detail AO using neighboring depth pixels: adds a lot of detail but also reduces temporal stability (adds aliasing).
|
||||||
|
FFX_CACAO_Bool generateNormals; ///< This option should be set to FFX_CACAO_TRUE if FidelityFX-CACAO should reconstruct a normal buffer from the depth buffer. It is required to be FFX_CACAO_TRUE if no normal buffer is provided.
|
||||||
|
float bilateralSigmaSquared; ///< [0.0, ~ ] Sigma squared value for use in bilateral upsampler giving Gaussian blur term. Should be greater than 0.0.
|
||||||
|
float bilateralSimilarityDistanceSigma; ///< [0.0, ~ ] Sigma squared value for use in bilateral upsampler giving similarity weighting for neighbouring pixels. Should be greater than 0.0.
|
||||||
|
} FFX_CACAO_Settings;
|
||||||
|
|
||||||
|
static const FFX_CACAO_Settings FFX_CACAO_DEFAULT_SETTINGS = {
|
||||||
|
/* radius */ 1.2f,
|
||||||
|
/* shadowMultiplier */ 1.0f,
|
||||||
|
/* shadowPower */ 1.50f,
|
||||||
|
/* shadowClamp */ 0.98f,
|
||||||
|
/* horizonAngleThreshold */ 0.06f,
|
||||||
|
/* fadeOutFrom */ 50.0f,
|
||||||
|
/* fadeOutTo */ 300.0f,
|
||||||
|
/* qualityLevel */ FFX_CACAO_QUALITY_HIGHEST,
|
||||||
|
/* adaptiveQualityLimit */ 0.45f,
|
||||||
|
/* blurPassCount */ 2,
|
||||||
|
/* sharpness */ 0.98f,
|
||||||
|
/* temporalSupersamplingAngleOffset */ 0.0f,
|
||||||
|
/* temporalSupersamplingRadiusOffset */ 0.0f,
|
||||||
|
/* detailShadowStrength */ 0.5f,
|
||||||
|
/* generateNormals */ FFX_CACAO_FALSE,
|
||||||
|
/* bilateralSigmaSquared */ 5.0f,
|
||||||
|
/* bilateralSimilarityDistanceSigma */ 0.01f,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
A C++ structure for the constant buffer used by FidelityFX CACAO.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_Constants {
|
||||||
|
float DepthUnpackConsts[2];
|
||||||
|
float CameraTanHalfFOV[2];
|
||||||
|
|
||||||
|
float NDCToViewMul[2];
|
||||||
|
float NDCToViewAdd[2];
|
||||||
|
|
||||||
|
float DepthBufferUVToViewMul[2];
|
||||||
|
float DepthBufferUVToViewAdd[2];
|
||||||
|
|
||||||
|
float EffectRadius;
|
||||||
|
float EffectShadowStrength;
|
||||||
|
float EffectShadowPow;
|
||||||
|
float EffectShadowClamp;
|
||||||
|
|
||||||
|
float EffectFadeOutMul;
|
||||||
|
float EffectFadeOutAdd;
|
||||||
|
float EffectHorizonAngleThreshold;
|
||||||
|
float EffectSamplingRadiusNearLimitRec;
|
||||||
|
|
||||||
|
float DepthPrecisionOffsetMod;
|
||||||
|
float NegRecEffectRadius;
|
||||||
|
float LoadCounterAvgDiv;
|
||||||
|
float AdaptiveSampleCountLimit;
|
||||||
|
|
||||||
|
float InvSharpness;
|
||||||
|
int PassIndex;
|
||||||
|
float BilateralSigmaSquared;
|
||||||
|
float BilateralSimilarityDistanceSigma;
|
||||||
|
|
||||||
|
float PatternRotScaleMatrices[5][4];
|
||||||
|
|
||||||
|
float NormalsUnpackMul;
|
||||||
|
float NormalsUnpackAdd;
|
||||||
|
float DetailAOStrength;
|
||||||
|
float Dummy0;
|
||||||
|
|
||||||
|
float SSAOBufferDimensions[2];
|
||||||
|
float SSAOBufferInverseDimensions[2];
|
||||||
|
|
||||||
|
float DepthBufferDimensions[2];
|
||||||
|
float DepthBufferInverseDimensions[2];
|
||||||
|
|
||||||
|
int DepthBufferOffset[2];
|
||||||
|
float PerPassFullResUVOffset[2];
|
||||||
|
|
||||||
|
float InputOutputBufferDimensions[2];
|
||||||
|
float InputOutputBufferInverseDimensions[2];
|
||||||
|
|
||||||
|
float ImportanceMapDimensions[2];
|
||||||
|
float ImportanceMapInverseDimensions[2];
|
||||||
|
|
||||||
|
float DeinterleavedDepthBufferDimensions[2];
|
||||||
|
float DeinterleavedDepthBufferInverseDimensions[2];
|
||||||
|
|
||||||
|
float DeinterleavedDepthBufferOffset[2];
|
||||||
|
float DeinterleavedDepthBufferNormalisedOffset[2];
|
||||||
|
|
||||||
|
FFX_CACAO_Matrix4x4 NormalsWorldToViewspaceMatrix;
|
||||||
|
} FFX_CACAO_Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
A structure containing sizes of each of the buffers used by FidelityFX CACAO.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_BufferSizeInfo {
|
||||||
|
uint32_t inputOutputBufferWidth;
|
||||||
|
uint32_t inputOutputBufferHeight;
|
||||||
|
|
||||||
|
uint32_t ssaoBufferWidth;
|
||||||
|
uint32_t ssaoBufferHeight;
|
||||||
|
|
||||||
|
uint32_t depthBufferXOffset;
|
||||||
|
uint32_t depthBufferYOffset;
|
||||||
|
|
||||||
|
uint32_t depthBufferWidth;
|
||||||
|
uint32_t depthBufferHeight;
|
||||||
|
|
||||||
|
uint32_t deinterleavedDepthBufferXOffset;
|
||||||
|
uint32_t deinterleavedDepthBufferYOffset;
|
||||||
|
|
||||||
|
uint32_t deinterleavedDepthBufferWidth;
|
||||||
|
uint32_t deinterleavedDepthBufferHeight;
|
||||||
|
|
||||||
|
uint32_t importanceMapWidth;
|
||||||
|
uint32_t importanceMapHeight;
|
||||||
|
|
||||||
|
uint32_t downsampledSsaoBufferWidth;
|
||||||
|
uint32_t downsampledSsaoBufferHeight;
|
||||||
|
} FFX_CACAO_BufferSizeInfo;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update buffer size info for resolution width x height.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
FFX_CACAO_BufferSizeInfo bufferSizeInfo = {};
|
||||||
|
FFX_CACAO_UpdateBufferSizeInfo(width, height, useDownsampledSsao, &bufferSizeInfo);
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\param width Screen width.
|
||||||
|
\param height Screen height.
|
||||||
|
\param useDownsampledSsao Whether FFX CACAO should use downsampling.
|
||||||
|
*/
|
||||||
|
void FFX_CACAO_UpdateBufferSizeInfo(uint32_t width, uint32_t height, FFX_CACAO_Bool useDownsampledSsao, FFX_CACAO_BufferSizeInfo* bsi);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the contents of the FFX CACAO constant buffer (an FFX_CACAO_Constants struct). Note, this function does not update
|
||||||
|
per pass constants.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
FFX_CACAO_Matrix4x4 proj = ...; // projection matrix for the frame
|
||||||
|
FFX_CACAO_Matrix4x4 normalsToView = ...; // normals world space to view space matrix for the frame
|
||||||
|
FFX_CACAO_Settings settings = ...; // settings
|
||||||
|
FFX_CACAO_BufferSizeInfo bufferSizeInfo = ...; // buffer size info
|
||||||
|
|
||||||
|
FFX_CACAO_Constants constants = {};
|
||||||
|
FFX_CACAO_UpdateConstants(&constants, &settings, &bufferSizeInfo, &proj, &normalsToView);
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\param consts FFX_CACAO_Constants constant buffer.
|
||||||
|
\param settings FFX_CACAO_Settings settings.
|
||||||
|
\param bufferSizeInfo FFX_CACAO_BufferSizeInfo buffer size info.
|
||||||
|
\param proj Projection matrix for the frame.
|
||||||
|
\param normalsToView Normals world space to view space matrix for the frame.
|
||||||
|
*/
|
||||||
|
void FFX_CACAO_UpdateConstants(FFX_CACAO_Constants* consts, const FFX_CACAO_Settings* settings, const FFX_CACAO_BufferSizeInfo* bufferSizeInfo, const FFX_CACAO_Matrix4x4* proj, const FFX_CACAO_Matrix4x4* normalsToView);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the contents of the FFX CACAO constant buffer (an FFX_CACAO_Constants struct) with per pass constants.
|
||||||
|
FFX CACAO runs 4 passes which use different constants. It is recommended to have four separate FFX_CACAO_Constants structs
|
||||||
|
each filled with constants for each of the 4 passes.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
FFX_CACAO_Settings settings = ...; // settings
|
||||||
|
FFX_CACAO_BufferSizeInfo bufferSizeInfo = ...; // buffer size info
|
||||||
|
|
||||||
|
FFX_CACAO_Constants perPassConstants[4] = {};
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
FFX_CACAO_UpdatePerPassConstants(&perPassConstants[i], &settings, &bufferSizeInfo, i);
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\param consts FFX_CACAO_Constants constants buffer.
|
||||||
|
\param settings FFX_CACAO_Settings settings.
|
||||||
|
\param bufferSizeInfo FFX_CACAO_BufferSizeInfo buffer size info.
|
||||||
|
\param pass pass number.
|
||||||
|
*/
|
||||||
|
void FFX_CACAO_UpdatePerPassConstants(FFX_CACAO_Constants* consts, const FFX_CACAO_Settings* settings, const FFX_CACAO_BufferSizeInfo* bufferSizeInfo, int pass);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,312 @@
|
|||||||
|
// Modifications Copyright © 2021. Advanced Micro Devices, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (c) 2016, Intel Corporation
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
|
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is 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 Software.
|
||||||
|
// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// File changes (yyyy-mm-dd)
|
||||||
|
// 2016-09-07: filip.strugar@intel.com: first commit
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/*! \file */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ffx_cacao.h"
|
||||||
|
|
||||||
|
// #define FFX_CACAO_ENABLE_PROFILING
|
||||||
|
// #define FFX_CACAO_ENABLE_D3D12
|
||||||
|
// #define FFX_CACAO_ENABLE_VULKAN
|
||||||
|
|
||||||
|
#ifdef FFX_CACAO_ENABLE_D3D12
|
||||||
|
#include <d3d12.h>
|
||||||
|
#endif
|
||||||
|
#ifdef FFX_CACAO_ENABLE_VULKAN
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
The return codes for the API functions.
|
||||||
|
*/
|
||||||
|
typedef enum FFX_CACAO_Status {
|
||||||
|
FFX_CACAO_STATUS_OK = 0,
|
||||||
|
FFX_CACAO_STATUS_INVALID_ARGUMENT = -1,
|
||||||
|
FFX_CACAO_STATUS_INVALID_POINTER = -2,
|
||||||
|
FFX_CACAO_STATUS_OUT_OF_MEMORY = -3,
|
||||||
|
FFX_CACAO_STATUS_FAILED = -4,
|
||||||
|
} FFX_CACAO_Status;
|
||||||
|
|
||||||
|
#ifdef FFX_CACAO_ENABLE_D3D12
|
||||||
|
/**
|
||||||
|
A struct containing all of the data used by FidelityFX-CACAO.
|
||||||
|
A context corresponds to an ID3D12Device.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_D3D12Context FFX_CACAO_D3D12Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The parameters for creating a context.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_D3D12ScreenSizeInfo {
|
||||||
|
uint32_t width; ///< width of the input/output buffers
|
||||||
|
uint32_t height; ///< height of the input/output buffers
|
||||||
|
ID3D12Resource *depthBufferResource; ///< pointer to depth buffer ID3D12Resource
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC depthBufferSrvDesc; ///< depth buffer D3D12_SHADER_RESOURCE_VIEW_DESC
|
||||||
|
ID3D12Resource *normalBufferResource; ///< optional pointer to normal buffer ID3D12Resource (leave as NULL if none is provided)
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC normalBufferSrvDesc; ///< normal buffer D3D12_SHADER_RESOURCE_VIEW_DESC
|
||||||
|
ID3D12Resource *outputResource; ///< pointer to output buffer ID3D12Resource
|
||||||
|
D3D12_UNORDERED_ACCESS_VIEW_DESC outputUavDesc; ///< output buffer D3D12_UNORDERED_ACCESS_VIEW_DESC
|
||||||
|
FFX_CACAO_Bool useDownsampledSsao; ///< Whether SSAO should be generated at native resolution or half resolution. It is recommended to enable this setting for improved performance.
|
||||||
|
} FFX_CACAO_D3D12ScreenSizeInfo;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FFX_CACAO_ENABLE_VULKAN
|
||||||
|
/**
|
||||||
|
A struct containing all of the data used by FidelityFX-CACAO.
|
||||||
|
A context corresponds to a VkDevice.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_VkContext FFX_CACAO_VkContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Miscellaneous flags for used for Vulkan context creation by FidelityFX-CACAO
|
||||||
|
*/
|
||||||
|
typedef enum FFX_CACAO_VkCreateFlagsBits {
|
||||||
|
FFX_CACAO_VK_CREATE_USE_16_BIT = 0x00000001, ///< Flag controlling whether 16-bit optimisations are enabled in shaders.
|
||||||
|
FFX_CACAO_VK_CREATE_USE_DEBUG_MARKERS = 0x00000002, ///< Flag controlling whether debug markers should be used.
|
||||||
|
FFX_CACAO_VK_CREATE_NAME_OBJECTS = 0x00000004, ///< Flag controlling whether Vulkan objects should be named.
|
||||||
|
} FFX_CACAO_VkCreateFlagsBits;
|
||||||
|
typedef uint32_t FFX_CACAO_VkCreateFlags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The parameters for creating a context.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_VkCreateInfo {
|
||||||
|
VkPhysicalDevice physicalDevice; ///< The VkPhysicalDevice corresponding to the VkDevice in use
|
||||||
|
VkDevice device; ///< The VkDevice to use FFX CACAO with
|
||||||
|
FFX_CACAO_VkCreateFlags flags; ///< Miscellaneous flags for context creation
|
||||||
|
} FFX_CACAO_VkCreateInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The parameters necessary when changing the screen size of FidelityFX CACAO.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_VkScreenSizeInfo {
|
||||||
|
uint32_t width; ///< width of the input/output buffers
|
||||||
|
uint32_t height; ///< height of the input/output buffers
|
||||||
|
VkImageView depthView; ///< An image view for the depth buffer, should be in layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL when used with FFX CACAO
|
||||||
|
VkImageView normalsView; ///< An optional image view for the normal buffer (may be VK_NULL_HANDLE). Should be in layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL when used with FFX CACAO
|
||||||
|
VkImage output; ///< An image for writing output from FFX CACAO, must have the same dimensions as the input
|
||||||
|
VkImageView outputView; ///< An image view corresponding to the output image.
|
||||||
|
FFX_CACAO_Bool useDownsampledSsao; ///< Whether SSAO should be generated at native resolution or half resolution. It is recommended to enable this setting for improved performance.
|
||||||
|
} FFX_CACAO_VkScreenSizeInfo;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FFX_CACAO_ENABLE_PROFILING
|
||||||
|
/**
|
||||||
|
A timestamp. The label gives the name of the stage of the effect, and the ticks is the number of GPU ticks spent on that stage.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_Timestamp {
|
||||||
|
const char *label; ///< name of timestamp stage
|
||||||
|
uint64_t ticks; ///< number of GPU ticks taken for stage
|
||||||
|
} FFX_CACAO_Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
An array of timestamps for detailed profiling information. The array timestamps contains numTimestamps entries.
|
||||||
|
Entry 0 of the timestamps array is guaranteed to be the total time taken by the effect.
|
||||||
|
*/
|
||||||
|
typedef struct FFX_CACAO_DetailedTiming {
|
||||||
|
uint32_t numTimestamps; ///< number of timetstamps in the array timestamps
|
||||||
|
FFX_CACAO_Timestamp timestamps[32]; ///< array of timestamps for each FFX CACAO stage
|
||||||
|
} FFX_CACAO_DetailedTiming;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FFX_CACAO_ENABLE_D3D12
|
||||||
|
/**
|
||||||
|
Gets the size in bytes required by a context. This is to be used to allocate space for the context.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
size_t FFX_CACAO_D3D12ContextSize = ffxCacaoD3D12GetContextSize();
|
||||||
|
FFX_CACAO_D3D12Context *context = (FFX_CACAO_D3D12Context*)malloc(FFX_CACAO_D3D12GetContextSize);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
FFX_CACAO_D3D12DestroyContext(context);
|
||||||
|
free(context);
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\return The size in bytes of an FFX_CACAO_D3D12Context.
|
||||||
|
*/
|
||||||
|
size_t FFX_CACAO_D3D12GetContextSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialises an FFX_CACAO_D3D12Context.
|
||||||
|
|
||||||
|
\param context A pointer to the context to initialise.
|
||||||
|
\param device A pointer to the D3D12 device.
|
||||||
|
\return The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_D3D12InitContext(FFX_CACAO_D3D12Context* context, ID3D12Device* device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Destroys an FFX_CACAO_D3D12Context.
|
||||||
|
|
||||||
|
\param context A pointer to the context to be destroyed.
|
||||||
|
\return The corresponding error code.
|
||||||
|
|
||||||
|
\note This function does not destroy screen size dependent resources, and must be called after FFX_CACAO_D3D12DestroyScreenSizeDependentResources.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_D3D12DestroyContext(FFX_CACAO_D3D12Context* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialises screen size dependent resources for the FFX_CACAO_D3D12Context.
|
||||||
|
|
||||||
|
\param context A pointer to the FFX_CACAO_D3D12Context.
|
||||||
|
\param info A pointer to an FFX_CACAO_D3D12ScreenSizeInfo struct containing screen size info.
|
||||||
|
\return The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_D3D12InitScreenSizeDependentResources(FFX_CACAO_D3D12Context* context, const FFX_CACAO_D3D12ScreenSizeInfo* info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Destroys screen size dependent resources for the FFX_CACAO_D3D12Context.
|
||||||
|
|
||||||
|
\param context A pointer to the FFX_CACAO_D3D12Context.
|
||||||
|
\return The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_D3D12DestroyScreenSizeDependentResources(FFX_CACAO_D3D12Context* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the settings of the FFX_CACAO_D3D12Context to those stored in the FFX_CACAO_Settings struct.
|
||||||
|
|
||||||
|
\param context A pointer to the FFX_CACAO_D3D12Context to update.
|
||||||
|
\param settings A pointer to the FFX_CACAO_Settings struct containing the new settings.
|
||||||
|
\return The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_D3D12UpdateSettings(FFX_CACAO_D3D12Context* context, const FFX_CACAO_Settings* settings);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Append commands for drawing FFX CACAO to the provided ID3D12GraphicsCommandList.
|
||||||
|
|
||||||
|
\param context A pointer to the FFX_CACAO_D3D12Context.
|
||||||
|
\param commandList A pointer to the ID3D12GraphicsCommandList to append commands to.
|
||||||
|
\param proj A pointer to the projection matrix.
|
||||||
|
\param normalsToView An optional pointer to a matrix for transforming normals to in the normal buffer to viewspace.
|
||||||
|
\return The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_D3D12Draw(FFX_CACAO_D3D12Context* context, ID3D12GraphicsCommandList* commandList, const FFX_CACAO_Matrix4x4* proj, const FFX_CACAO_Matrix4x4* normalsToView);
|
||||||
|
|
||||||
|
#if FFX_CACAO_ENABLE_PROFILING
|
||||||
|
/**
|
||||||
|
Get detailed performance timings from the previous frame.
|
||||||
|
|
||||||
|
\param context A pointer to the FFX_CACAO_D3D12Context.
|
||||||
|
\param timings A pointer to an FFX_CACAO_DetailedTiming struct to fill in with detailed timings.
|
||||||
|
\result The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_D3D12GetDetailedTimings(FFX_CACAO_D3D12Context* context, FFX_CACAO_DetailedTiming* timings);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FFX_CACAO_ENABLE_VULKAN
|
||||||
|
/**
|
||||||
|
Gets the size in bytes required by a Vulkan context. This is to be used to allocate space for the context.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
size_t FFX_CACAO_VkContextSize = ffxCacaoVkGetContextSize();
|
||||||
|
FFX_CACAO_VkContext *context = (FFX_CACAO_VkContext*)malloc(FFX_CACAO_VkGetContextSize);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
FFX_CACAO_VkDestroyContext(context);
|
||||||
|
free(context);
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\return The size in bytes of an FFX_CACAO_VkContext.
|
||||||
|
*/
|
||||||
|
size_t FFX_CACAO_VkGetContextSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialises an FFX_CACAO_VkContext.
|
||||||
|
|
||||||
|
\param context A pointer to the context to initialise.
|
||||||
|
\param info A pointer to an FFX_CACAO_VkCreateInfo struct with parameters such as the vulkan device.
|
||||||
|
\return The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_VkInitContext(FFX_CACAO_VkContext* context, const FFX_CACAO_VkCreateInfo *info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Destroys an FFX_CACAO_VkContext.
|
||||||
|
|
||||||
|
\param context A pointer to the context to be destroyed.
|
||||||
|
\return The corresponding error code.
|
||||||
|
|
||||||
|
\note This function does not destroy screen size dependent resources, and must be called after FFX_CACAO_VkDestroyScreenSizeDependentResources.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_VkDestroyContext(FFX_CACAO_VkContext* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialises screen size dependent resources for the FFX_CACAO_VkContext.
|
||||||
|
|
||||||
|
\param context A pointer to the FFX_CACAO_VkContext.
|
||||||
|
\param info A pointer to an FFX_CACAO_VkScreenSizeInfo struct containing screen size info.
|
||||||
|
\return The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_VkInitScreenSizeDependentResources(FFX_CACAO_VkContext* context, const FFX_CACAO_VkScreenSizeInfo* info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Destroys screen size dependent resources for the FFX_CACAO_VkContext.
|
||||||
|
|
||||||
|
\param context A pointer to the FFX_CACAO_VkContext.
|
||||||
|
\return The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_VkDestroyScreenSizeDependentResources(FFX_CACAO_VkContext* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the settings of the FFX_CACAO_VkContext to those stored in the FFX_CACAO_Settings struct.
|
||||||
|
|
||||||
|
\param context A pointer to the FFX_CACAO_VkContext to update.
|
||||||
|
\param settings A pointer to the FFX_CACAO_Settings struct containing the new settings.
|
||||||
|
\return The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_VkUpdateSettings(FFX_CACAO_VkContext* context, const FFX_CACAO_Settings* settings);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Append commands for drawing FFX CACAO to the provided VkCommandBuffer.
|
||||||
|
|
||||||
|
\param context A pointer to the FFX_CACAO_VkContext.
|
||||||
|
\param commandList The VkCommandBuffer to append commands to.
|
||||||
|
\param proj A pointer to the projection matrix.
|
||||||
|
\param normalsToView An optional pointer to a matrix for transforming normals to in the normal buffer to viewspace.
|
||||||
|
\return The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_VkDraw(FFX_CACAO_VkContext* context, VkCommandBuffer commandList, const FFX_CACAO_Matrix4x4* proj, const FFX_CACAO_Matrix4x4* normalsToView);
|
||||||
|
|
||||||
|
#ifdef FFX_CACAO_ENABLE_PROFILING
|
||||||
|
/**
|
||||||
|
Get detailed performance timings from the previous frame.
|
||||||
|
|
||||||
|
\param context A pointer to the FFX_CACAO_VkContext.
|
||||||
|
\param timings A pointer to an FFX_CACAO_DetailedTiming struct to fill in with detailed timings.
|
||||||
|
\result The corresponding error code.
|
||||||
|
*/
|
||||||
|
FFX_CACAO_Status FFX_CACAO_VkGetDetailedTimings(FFX_CACAO_VkContext* context, FFX_CACAO_DetailedTiming* timings);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
# FidelityFX CACAO
|
||||||
|
|
||||||
|
The **FidelityFX CACAO** library implements screen space ambient occlusion for use in real time applications. A full sample can be found on the [FidelityFX CACAO Github page](https://github.com/GPUOpen-Effects/FidelityFX-CACAO).
|
||||||
|
|
||||||
|
# Project Integration
|
||||||
|
|
||||||
|
FidelityFX CACAO comes with two main header files, `ffx-cacao/inc/ffx_cacao.h` and `ffx-cacao/inc/ffx_cacao_impl.h`. The file `ffx-cacao/inc/ffx_cacao.h` contains reusable C++ functions and struct definitions for integration of FidelityFX CACAO into custom engines. The functions declared in this header file are defined in `ffx-cacao/src/ffx_cacao.cpp`. The header file `ffx-cacao/inc/ffx_cacao_impl.h` is for use in quick integration of FidelityFX CACAO into DX12 and Vulkan engines. The functions declared in this file are defined in `ffx-cacao/src/ffx_cacao_impl.cpp`, which serves as a reference implementation of FidelityFX CACAO.
|
||||||
|
|
||||||
|
# Reusable Functions and Structs
|
||||||
|
|
||||||
|
The reusable functions and structs provided in `ffx-cacao/src/ffx_cacao.h` are documented via doxygen comments in the header file itself. The functions and structs are used to initialise the constant buffers used by FidelityFX CACAO from a user friendly settings struct `FFX_CACAO_Settings`.
|
||||||
|
|
||||||
|
# Reference Implementation
|
||||||
|
|
||||||
|
The reference implementation of FidelityFX CACAO supports three compile time options. These are:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
FFX_CACAO_ENABLE_D3D12
|
||||||
|
FFX_CACAO_ENABLE_VK
|
||||||
|
FFX_CACAO_ENABLE_PROFILING
|
||||||
|
```
|
||||||
|
|
||||||
|
For use with D3D12 or Vulkan, the symbols `FFX_CACAO_ENABLE_D3D12` or `FFX_CACAO_ENABLE_VK` must be defined. If you wish to get detailed timings from FFX CACAO the symbol `FFX_CACAO_ENABLE_PROFILING` must be defined. These symbols can either be defined in the header `ffx-cacao/inc/ffx_cacao_impl.h` itself by uncommenting the respective definitions, or they can defined in compiler flags. The provided sample of FFX CACAO defines these symbols using compiler flags.
|
||||||
|
|
||||||
|
# Context Initialisation and Shutdown
|
||||||
|
|
||||||
|
First the FFX CACAO header must be included. This can be found at `ffx-cacao/inc/ffx_cacao_impl.h`. Then a context must be created. This is usually done only once per device. To create a context you must first query for the size of a context, allocate space for a context, then inintialise the context.
|
||||||
|
|
||||||
|
|
||||||
|
For D3D12 the initialisation and shutdown processes are as follows:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
// initialisation
|
||||||
|
size_t ffxCacaoContextSize = ffxCacaoD3D12GetContextSize();
|
||||||
|
FfxCacaoD3D12Context *context = (FfxCacaoD3D12Context*)malloc(ffxCacaoContextSize);
|
||||||
|
assert(context);
|
||||||
|
FfxCacaoStatus status = ffxCacaoD3D12InitContext(context, d3d12Device);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
...
|
||||||
|
// finalisation
|
||||||
|
status = ffxCacaoD3D12DestroyContext(context);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
free(context);
|
||||||
|
```
|
||||||
|
|
||||||
|
The only argument required for initialisation of a D3D12 context is an `ID3D12Device*` for the D3D12 device.
|
||||||
|
|
||||||
|
For Vulkan the initialisation and shutdown processes are as follows:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
// initialisation
|
||||||
|
size_t ffxCacaoContextSize = ffxCacaoVkGetContextSize();
|
||||||
|
FfxCacaoVkContext *context = (FfxCacaoVkContext*)malloc(ffxCacaoContextSize);
|
||||||
|
assert(context);
|
||||||
|
FfxCacaoVkCreateInfo info = {};
|
||||||
|
info.physicalDevice = vkPhysicalDevice;
|
||||||
|
info.device = vkDevice;
|
||||||
|
info.flags = FFX_CACAO_VK_CREATE_USE_16_BIT | FFX_CACAO_VK_CREATE_USE_DEBUG_MARKERS | FFX_CACAO_VK_CREATE_NAME_OBJECTS;
|
||||||
|
FfxCacaoStatus status = ffxCacaoVkInitContext(context, &info);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
...
|
||||||
|
// finalisation
|
||||||
|
status = ffxCacaoVkDestroyContext(context);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
free(context);
|
||||||
|
```
|
||||||
|
|
||||||
|
To initialise the FFX CACAO context in Vulkan, the parameters of the `FfxCacaoVkCreateInfo` struct must be filled in. These are the Vulkan physical device and Vulkan device, and a field of flags. The flags is a bitwise combination of the following options. The option `FFX_CACAO_VK_CREATE_USE_16_BIT` enables 16 bit optimisations, and requires a Vulkan device created using 16 bit extensions. This option is strongly recommended for compatible devices. The options `FFX_CACAO_VK_CREATE_USE_DEBUG_MARKERS` and `FFX_CACAO_VK_CREATE_NAME_OBJECTS` will add debug markers and name objects (e.g. textures, shaders) to aid inspection of FFX CACAO with a frame debugger.
|
||||||
|
|
||||||
|
# Screen Size Dependent Resource Initialisation
|
||||||
|
|
||||||
|
Once the context is initialised, it will need to have screen size dependent resources initialised each time the screen size is changed. To do this, an `FfxCacaoD3D12ScreenSizeInfo` struct must be filled out. The FFX CACAO effect is computed using a depth buffer and optional normal buffer. FFX CACAO writes its output to a user provided output buffer. The depth buffer, normal buffer and output buffer provided to FFX CACAO must all be the same size.
|
||||||
|
|
||||||
|
|
||||||
|
For FFX CACAO D3D12, the process is as follows:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
// initialisation
|
||||||
|
FfxCacaoD3D12ScreenSizeInfo screenSizeInfo = {};
|
||||||
|
screenSizeInfo.width = /* width of the input/output buffers */;
|
||||||
|
screenSizeInfo.height = /* height of the input/output buffers */;
|
||||||
|
screenSizeInfo.depthBufferResource = /* ID3D12Resource* for the depth input buffer */;
|
||||||
|
screenSizeInfo.depthBufferSrvDesc = /* D3D12_SHADER_RESOURCE_VIEW_DESC for the depth input buffer */;
|
||||||
|
screenSizeInfo.normalBufferResource = /* ID3D12Resource* for the normal input buffer - or NULL if none shall be provided */;
|
||||||
|
screenSizeInfo.normalBufferSrvDesc = /* D3D12_SHADER_RESOURCE_VIEW_DESC for the normal input buffer */;
|
||||||
|
screenSizeInfo.outputResource = /* ID3D12Resource* for the output buffer */;
|
||||||
|
screenSizeInfo.depthBufferSrvDesc = /* D3D12_SHADER_RESOURCE_VIEW_DESC for the depth output */;
|
||||||
|
status = ffxCacaoD3D12InitScreenSizeDependentResources(context, &screenSizeInfo);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
...
|
||||||
|
// finalisation
|
||||||
|
status = ffxCacaoD3D12DestroyScreenSizeDependentResources(context);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
```
|
||||||
|
|
||||||
|
For FFX CACAO Vulkan, the process is as follows:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
// Initialisation
|
||||||
|
FfxCacaoVkScreenSizeInfo screenSizeInfo = {};
|
||||||
|
screenSizeInfo.width = /* width of the input/output buffers */;
|
||||||
|
screenSizeInfo.height = /* height of the input/output buffers */;
|
||||||
|
screenSizeInfo.depthView = /* a VkImageView for the depth buffer, should be in layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL */;
|
||||||
|
screenSizeInfo.normalsView = /* an optional VkImageView for the normal buffer (VK_NULL_HANDLE if not provided), should be in layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL */;
|
||||||
|
screenSizeInfo.output = /* a VkImage for writing the output of FFX CACAO */;
|
||||||
|
screenSizeInfo.outputView = /* a VkImageView corresponding to the VkImage for writing the output of FFX CACAO */;
|
||||||
|
status = ffxCacaoVkInitScreenSizeDependentResources(context, &screenSizeInfo);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
...
|
||||||
|
// finalisation
|
||||||
|
status = ffxCacaoVkDestroyScreenSizeDependentResources(context);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
```
|
||||||
|
|
||||||
|
# Initialising/Updating FFX CACAO Settings
|
||||||
|
|
||||||
|
The settings for the FFX CACAO effect may be changed via the `FfxCacaoSettings` struct and the `ffxCacaoD3D12UpdateSettings` or `ffxCacaoVkUpdateSettings` functions as follows.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
FfxCacaoSettings settings = {};
|
||||||
|
settings.radius = /* world view radius of the occlusion sphere */;
|
||||||
|
settings.shadowMultiplier = /* effect strength linear multiplier */;
|
||||||
|
settings.shadowPower = /* effect strength power multiplier */;
|
||||||
|
settings.shadowClamp = /* effect max limit */;
|
||||||
|
settings.horizonAngleThreshold = /* minimum horizon angle for contributions to occlusion to limit self shadowing */
|
||||||
|
settings.fadeOutFrom = /* effect fade out from world space distance */;
|
||||||
|
settings.fadeOutTo = /* effect fade out to world space distance */;
|
||||||
|
settings.qualityLevel = /* the quality of the effect, ranging from lowest to highest (adaptive). This affects the number of samples taken to generate SSAO. */;
|
||||||
|
settings.adaptiveQualityLimit = /* quality limit for adaptive quality */;
|
||||||
|
settings.blurPassCount = /* a number of edge sensitive blurs from 1 to 8 to perform after SSAO generation */;
|
||||||
|
settings.sharpness = /* how much to bleed over edges - 0 = ignore edges, 1 = don't bleed over edges */;
|
||||||
|
settings.temporalSupersamplingAngleOffset = /* sampling angle offset for temporal super sampling */;
|
||||||
|
settings.temporalSupersamplingRaidusOffset = /* sampling effect radius offset for temporal super sampling */;
|
||||||
|
settings.detailShadowStrength = /* used to generate details in high res AO */;
|
||||||
|
settings.generateNormals = /* should the effect generate normals from the depth buffer or use a provided normal buffer */;
|
||||||
|
settings.bilateralSigmaSquared = /* a parameter for use in bilateral upsampling. Higher values create more blur to help reduce noise */;
|
||||||
|
settings.bilateralSimilarityDistanceSigma = /* a parameter for use in bilateral upsampling. Lower values create reduce bluring across edge boundaries */;
|
||||||
|
```
|
||||||
|
|
||||||
|
These settings can be set to sensible defaults from the constant `FFX_CACAO_DEFAULT_SETTINGS` and updated using the function `ffxCacaoD3D12UpdateSettings` or `ffxCacaoVkUpdateSettings` as follows.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
FfxCacaoSettings settings = FFX_CACAO_DEFAULT_SETTINGS;
|
||||||
|
status = ffxCacaoD3D12UpdateSettings(context, &settings);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the `FFX_CACAO_DEFAULT_SETTINGS` provides a sensible quick start for high quality settings. The parameters `radius`, `fadeOutFrom` and `fadeOutTo` should
|
||||||
|
be changed to match the world space of the target scene, and the parameter `blurPassCount` is recommended to be increased for lower quality settings. A more complete
|
||||||
|
set of sensible defaults may be found in the FFX CACAO sample in the file `sample/src/Common/FFX_CACAO_Common.h`, where multiple parameters have been varied to move
|
||||||
|
from high to low quality presets.
|
||||||
|
|
||||||
|
# Drawing
|
||||||
|
|
||||||
|
In D3D12, FFX CACAO can be called to add commands to a `ID3D12GraphicsCommandList` using the `ffxCacaoD3D12Draw` function as follows:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
FfxCacaoMatrix4x4 proj = /* row major projection matrix */;
|
||||||
|
FfxCacaoMatrix4x4 normalsToView = /* row major matrix to convert normals to viewspace */
|
||||||
|
status = ffxCacaoD3D12Draw(context, commandList, &proj, &normalsToView);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
```
|
||||||
|
|
||||||
|
In Vulkan, FFX CACAO can add commands to a `VkCommandBuffer` using the `ffxCacaoVkDraw` function as follows:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
FfxCacaoMatrix4x4 proj = /* row major projection matrix */;
|
||||||
|
FfxCacaoMatrix4x4 normalsToView = /* row major matrix to convert normals to viewspace */
|
||||||
|
status = ffxCacaoVkDraw(context, commandBuffer, &proj, &normalsToView);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
```
|
||||||
|
|
||||||
|
The matrix `proj` is the projection matrix used from viewspace to normalised device coordinates. The matrix `normalsToView` is a matrix to convert the normals provided in the normal buffer to viewspace.
|
||||||
|
|
||||||
|
# Profiling
|
||||||
|
|
||||||
|
Finally, if the preprocessor symbol `FFX_CACAO_ENABLE_PROFILING` is defined, then detailed timings can be read from FFX CACAO using the functions `ffxCacaoD3D12GetDetailedTimings` and `ffxCacaoVkGetDetailedTimings` for D3D12 and Vulkan respectively. These functions should be called as follows:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
FfxCacaoDetailedTiming timings = {};
|
||||||
|
uint64_t gpuTicksPerMicrosecond;
|
||||||
|
FfxCacaoStatus status = ffxCacaoD3D12GetDetailedTimings(context, &timings, &gpuTicksPerMicrosecond);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
```
|
||||||
|
|
||||||
|
The timings returned are in GPU ticks. These can be converted into seconds using the value returned in the `gpuTicksPerMicrosecond` parameter above.
|
||||||
|
|
||||||
|
Or in Vulkan:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
FfxCacaoDetailedTiming timings = {};
|
||||||
|
FfxCacaoStatus status = ffxCacaoD3D12GetDetailedTimings(context, &timings);
|
||||||
|
assert(status == FFX_CACAO_STATUS_OK);
|
||||||
|
```
|
||||||
|
|
||||||
|
The timings returned are measured in GPU ticks, and will need to be converted using th GPU ticks per microsecond parameter available from `vkGetPhysicalDeviceLimits`.
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
%echo off
|
||||||
|
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
set cauldron_dxc=..\..\sample\libs\cauldron\libs\DXC\bin\dxc.exe -T cs_6_2
|
||||||
|
|
||||||
|
if not exist "PrecompiledShadersDXIL" mkdir "PrecompiledShadersDXIL"
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOClearLoadCounter.h -Vn CSClearLoadCounterDXIL -E FFX_CACAO_ClearLoadCounter ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPrepareDownsampledDepths.h -Vn CSPrepareDownsampledDepthsDXIL -E FFX_CACAO_PrepareDownsampledDepths ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPrepareNativeDepths.h -Vn CSPrepareNativeDepthsDXIL -E FFX_CACAO_PrepareNativeDepths ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPrepareDownsampledDepthsAndMips.h -Vn CSPrepareDownsampledDepthsAndMipsDXIL -E FFX_CACAO_PrepareDownsampledDepthsAndMips ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPrepareNativeDepthsAndMips.h -Vn CSPrepareNativeDepthsAndMipsDXIL -E FFX_CACAO_PrepareNativeDepthsAndMips ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPrepareDownsampledNormals.h -Vn CSPrepareDownsampledNormalsDXIL -E FFX_CACAO_PrepareDownsampledNormals ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPrepareNativeNormals.h -Vn CSPrepareNativeNormalsDXIL -E FFX_CACAO_PrepareNativeNormals ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPrepareDownsampledNormalsFromInputNormals.h -Vn CSPrepareDownsampledNormalsFromInputNormalsDXIL -E FFX_CACAO_PrepareDownsampledNormalsFromInputNormals ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPrepareNativeNormalsFromInputNormals.h -Vn CSPrepareNativeNormalsFromInputNormalsDXIL -E FFX_CACAO_PrepareNativeNormalsFromInputNormals ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPrepareDownsampledDepthsHalf.h -Vn CSPrepareDownsampledDepthsHalfDXIL -E FFX_CACAO_PrepareDownsampledDepthsHalf ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPrepareNativeDepthsHalf.h -Vn CSPrepareNativeDepthsHalfDXIL -E FFX_CACAO_PrepareNativeDepthsHalf ffx_cacao.hlsl
|
||||||
|
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOGenerateQ0.h -Vn CSGenerateQ0DXIL -E FFX_CACAO_GenerateQ0 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOGenerateQ1.h -Vn CSGenerateQ1DXIL -E FFX_CACAO_GenerateQ1 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOGenerateQ2.h -Vn CSGenerateQ2DXIL -E FFX_CACAO_GenerateQ2 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOGenerateQ3.h -Vn CSGenerateQ3DXIL -E FFX_CACAO_GenerateQ3 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOGenerateQ3Base.h -Vn CSGenerateQ3BaseDXIL -E FFX_CACAO_GenerateQ3Base ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOGenerateImportanceMap.h -Vn CSGenerateImportanceMapDXIL -E FFX_CACAO_GenerateImportanceMap ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPostprocessImportanceMapA.h -Vn CSPostprocessImportanceMapADXIL -E FFX_CACAO_PostprocessImportanceMapA ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOPostprocessImportanceMapB.h -Vn CSPostprocessImportanceMapBDXIL -E FFX_CACAO_PostprocessImportanceMapB ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOEdgeSensitiveBlur1.h -Vn CSEdgeSensitiveBlur1DXIL -E FFX_CACAO_EdgeSensitiveBlur1 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOEdgeSensitiveBlur2.h -Vn CSEdgeSensitiveBlur2DXIL -E FFX_CACAO_EdgeSensitiveBlur2 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOEdgeSensitiveBlur3.h -Vn CSEdgeSensitiveBlur3DXIL -E FFX_CACAO_EdgeSensitiveBlur3 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOEdgeSensitiveBlur4.h -Vn CSEdgeSensitiveBlur4DXIL -E FFX_CACAO_EdgeSensitiveBlur4 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOEdgeSensitiveBlur5.h -Vn CSEdgeSensitiveBlur5DXIL -E FFX_CACAO_EdgeSensitiveBlur5 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOEdgeSensitiveBlur6.h -Vn CSEdgeSensitiveBlur6DXIL -E FFX_CACAO_EdgeSensitiveBlur6 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOEdgeSensitiveBlur7.h -Vn CSEdgeSensitiveBlur7DXIL -E FFX_CACAO_EdgeSensitiveBlur7 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOEdgeSensitiveBlur8.h -Vn CSEdgeSensitiveBlur8DXIL -E FFX_CACAO_EdgeSensitiveBlur8 ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOApply.h -Vn CSApplyDXIL -E FFX_CACAO_Apply ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAONonSmartApply.h -Vn CSNonSmartApplyDXIL -E FFX_CACAO_NonSmartApply ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAONonSmartHalfApply.h -Vn CSNonSmartHalfApplyDXIL -E FFX_CACAO_NonSmartHalfApply ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOUpscaleBilateral5x5NonSmart.h -Vn CSUpscaleBilateral5x5NonSmartDXIL -E FFX_CACAO_UpscaleBilateral5x5NonSmart ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOUpscaleBilateral5x5Smart.h -Vn CSUpscaleBilateral5x5SmartDXIL -E FFX_CACAO_UpscaleBilateral5x5Smart ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc% -Fh PrecompiledShadersDXIL/CACAOUpscaleBilateral5x5Half.h -Vn CSUpscaleBilateral5x5HalfDXIL -E FFX_CACAO_UpscaleBilateral5x5Half ffx_cacao.hlsl
|
||||||
|
|
||||||
|
popd
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
%echo off
|
||||||
|
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
set cauldron_dxc_16=glslc -Wno-conversion -spirv -T cs_6_2 -enable-16bit-types -fspv-target-env=vulkan1.1 -fvk-s-shift 0 0 -fvk-b-shift 10 0 -fvk-t-shift 20 0 -fvk-u-shift 30 0
|
||||||
|
set cauldron_dxc_32=glslc -Wno-conversion -spirv -T cs_6_2 -fspv-target-env=vulkan1.1 -fvk-s-shift 0 0 -fvk-b-shift 10 0 -fvk-t-shift 20 0 -fvk-u-shift 30 0
|
||||||
|
|
||||||
|
if not exist "PrecompiledShadersSPIRV" mkdir "PrecompiledShadersSPIRV"
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOClearLoadCounter_16.h -Vn CSClearLoadCounterSPIRV16 -E FFX_CACAO_ClearLoadCounter ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPrepareDownsampledDepths_16.h -Vn CSPrepareDownsampledDepthsSPIRV16 -E FFX_CACAO_PrepareDownsampledDepths ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPrepareNativeDepths_16.h -Vn CSPrepareNativeDepthsSPIRV16 -E FFX_CACAO_PrepareNativeDepths ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPrepareDownsampledDepthsAndMips_16.h -Vn CSPrepareDownsampledDepthsAndMipsSPIRV16 -E FFX_CACAO_PrepareDownsampledDepthsAndMips ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPrepareNativeDepthsAndMips_16.h -Vn CSPrepareNativeDepthsAndMipsSPIRV16 -E FFX_CACAO_PrepareNativeDepthsAndMips ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPrepareDownsampledNormals_16.h -Vn CSPrepareDownsampledNormalsSPIRV16 -E FFX_CACAO_PrepareDownsampledNormals ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPrepareNativeNormals_16.h -Vn CSPrepareNativeNormalsSPIRV16 -E FFX_CACAO_PrepareNativeNormals ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPrepareDownsampledNormalsFromInputNormals_16.h -Vn CSPrepareDownsampledNormalsFromInputNormalsSPIRV16 -E FFX_CACAO_PrepareDownsampledNormalsFromInputNormals ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPrepareNativeNormalsFromInputNormals_16.h -Vn CSPrepareNativeNormalsFromInputNormalsSPIRV16 -E FFX_CACAO_PrepareNativeNormalsFromInputNormals ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPrepareDownsampledDepthsHalf_16.h -Vn CSPrepareDownsampledDepthsHalfSPIRV16 -E FFX_CACAO_PrepareDownsampledDepthsHalf ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPrepareNativeDepthsHalf_16.h -Vn CSPrepareNativeDepthsHalfSPIRV16 -E FFX_CACAO_PrepareNativeDepthsHalf ffx_cacao.hlsl
|
||||||
|
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOGenerateQ0_16.h -Vn CSGenerateQ0SPIRV16 -E FFX_CACAO_GenerateQ0 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOGenerateQ1_16.h -Vn CSGenerateQ1SPIRV16 -E FFX_CACAO_GenerateQ1 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOGenerateQ2_16.h -Vn CSGenerateQ2SPIRV16 -E FFX_CACAO_GenerateQ2 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOGenerateQ3_16.h -Vn CSGenerateQ3SPIRV16 -E FFX_CACAO_GenerateQ3 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOGenerateQ3Base_16.h -Vn CSGenerateQ3BaseSPIRV16 -E FFX_CACAO_GenerateQ3Base ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOGenerateImportanceMap_16.h -Vn CSGenerateImportanceMapSPIRV16 -E FFX_CACAO_GenerateImportanceMap ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPostprocessImportanceMapA_16.h -Vn CSPostprocessImportanceMapASPIRV16 -E FFX_CACAO_PostprocessImportanceMapA ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOPostprocessImportanceMapB_16.h -Vn CSPostprocessImportanceMapBSPIRV16 -E FFX_CACAO_PostprocessImportanceMapB ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur1_16.h -Vn CSEdgeSensitiveBlur1SPIRV16 -E FFX_CACAO_EdgeSensitiveBlur1 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur2_16.h -Vn CSEdgeSensitiveBlur2SPIRV16 -E FFX_CACAO_EdgeSensitiveBlur2 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur3_16.h -Vn CSEdgeSensitiveBlur3SPIRV16 -E FFX_CACAO_EdgeSensitiveBlur3 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur4_16.h -Vn CSEdgeSensitiveBlur4SPIRV16 -E FFX_CACAO_EdgeSensitiveBlur4 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur5_16.h -Vn CSEdgeSensitiveBlur5SPIRV16 -E FFX_CACAO_EdgeSensitiveBlur5 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur6_16.h -Vn CSEdgeSensitiveBlur6SPIRV16 -E FFX_CACAO_EdgeSensitiveBlur6 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur7_16.h -Vn CSEdgeSensitiveBlur7SPIRV16 -E FFX_CACAO_EdgeSensitiveBlur7 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur8_16.h -Vn CSEdgeSensitiveBlur8SPIRV16 -E FFX_CACAO_EdgeSensitiveBlur8 ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOApply_16.h -Vn CSApplySPIRV16 -E FFX_CACAO_Apply ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAONonSmartApply_16.h -Vn CSNonSmartApplySPIRV16 -E FFX_CACAO_NonSmartApply ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAONonSmartHalfApply_16.h -Vn CSNonSmartHalfApplySPIRV16 -E FFX_CACAO_NonSmartHalfApply ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOUpscaleBilateral5x5Smart_16.h -Vn CSUpscaleBilateral5x5SmartSPIRV16 -E FFX_CACAO_UpscaleBilateral5x5Smart ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOUpscaleBilateral5x5NonSmart_16.h -Vn CSUpscaleBilateral5x5NonSmartSPIRV16 -E FFX_CACAO_UpscaleBilateral5x5NonSmart ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_16% -Fh PrecompiledShadersSPIRV/CACAOUpscaleBilateral5x5Half_16.h -Vn CSUpscaleBilateral5x5HalfSPIRV16 -E FFX_CACAO_UpscaleBilateral5x5Half ffx_cacao.hlsl
|
||||||
|
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOClearLoadCounter_32.h -Vn CSClearLoadCounterSPIRV32 -E FFX_CACAO_ClearLoadCounter ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPrepareDownsampledDepths_32.h -Vn CSPrepareDownsampledDepthsSPIRV32 -E FFX_CACAO_PrepareDownsampledDepths ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPrepareNativeDepths_32.h -Vn CSPrepareNativeDepthsSPIRV32 -E FFX_CACAO_PrepareNativeDepths ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPrepareDownsampledDepthsAndMips_32.h -Vn CSPrepareDownsampledDepthsAndMipsSPIRV32 -E FFX_CACAO_PrepareDownsampledDepthsAndMips ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPrepareNativeDepthsAndMips_32.h -Vn CSPrepareNativeDepthsAndMipsSPIRV32 -E FFX_CACAO_PrepareNativeDepthsAndMips ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPrepareDownsampledNormals_32.h -Vn CSPrepareDownsampledNormalsSPIRV32 -E FFX_CACAO_PrepareDownsampledNormals ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPrepareNativeNormals_32.h -Vn CSPrepareNativeNormalsSPIRV32 -E FFX_CACAO_PrepareNativeNormals ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPrepareDownsampledNormalsFromInputNormals_32.h -Vn CSPrepareDownsampledNormalsFromInputNormalsSPIRV32 -E FFX_CACAO_PrepareDownsampledNormalsFromInputNormals ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPrepareNativeNormalsFromInputNormals_32.h -Vn CSPrepareNativeNormalsFromInputNormalsSPIRV32 -E FFX_CACAO_PrepareNativeNormalsFromInputNormals ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPrepareDownsampledDepthsHalf_32.h -Vn CSPrepareDownsampledDepthsHalfSPIRV32 -E FFX_CACAO_PrepareDownsampledDepthsHalf ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPrepareNativeDepthsHalf_32.h -Vn CSPrepareNativeDepthsHalfSPIRV32 -E FFX_CACAO_PrepareNativeDepthsHalf ffx_cacao.hlsl
|
||||||
|
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOGenerateQ0_32.h -Vn CSGenerateQ0SPIRV32 -E FFX_CACAO_GenerateQ0 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOGenerateQ1_32.h -Vn CSGenerateQ1SPIRV32 -E FFX_CACAO_GenerateQ1 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOGenerateQ2_32.h -Vn CSGenerateQ2SPIRV32 -E FFX_CACAO_GenerateQ2 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOGenerateQ3_32.h -Vn CSGenerateQ3SPIRV32 -E FFX_CACAO_GenerateQ3 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOGenerateQ3Base_32.h -Vn CSGenerateQ3BaseSPIRV32 -E FFX_CACAO_GenerateQ3Base ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOGenerateImportanceMap_32.h -Vn CSGenerateImportanceMapSPIRV32 -E FFX_CACAO_GenerateImportanceMap ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPostprocessImportanceMapA_32.h -Vn CSPostprocessImportanceMapASPIRV32 -E FFX_CACAO_PostprocessImportanceMapA ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOPostprocessImportanceMapB_32.h -Vn CSPostprocessImportanceMapBSPIRV32 -E FFX_CACAO_PostprocessImportanceMapB ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur1_32.h -Vn CSEdgeSensitiveBlur1SPIRV32 -E FFX_CACAO_EdgeSensitiveBlur1 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur2_32.h -Vn CSEdgeSensitiveBlur2SPIRV32 -E FFX_CACAO_EdgeSensitiveBlur2 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur3_32.h -Vn CSEdgeSensitiveBlur3SPIRV32 -E FFX_CACAO_EdgeSensitiveBlur3 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur4_32.h -Vn CSEdgeSensitiveBlur4SPIRV32 -E FFX_CACAO_EdgeSensitiveBlur4 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur5_32.h -Vn CSEdgeSensitiveBlur5SPIRV32 -E FFX_CACAO_EdgeSensitiveBlur5 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur6_32.h -Vn CSEdgeSensitiveBlur6SPIRV32 -E FFX_CACAO_EdgeSensitiveBlur6 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur7_32.h -Vn CSEdgeSensitiveBlur7SPIRV32 -E FFX_CACAO_EdgeSensitiveBlur7 ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOEdgeSensitiveBlur8_32.h -Vn CSEdgeSensitiveBlur8SPIRV32 -E FFX_CACAO_EdgeSensitiveBlur8 ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOApply_32.h -Vn CSApplySPIRV32 -E FFX_CACAO_Apply ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAONonSmartApply_32.h -Vn CSNonSmartApplySPIRV32 -E FFX_CACAO_NonSmartApply ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAONonSmartHalfApply_32.h -Vn CSNonSmartHalfApplySPIRV32 -E FFX_CACAO_NonSmartHalfApply ffx_cacao.hlsl
|
||||||
|
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOUpscaleBilateral5x5Smart_32.h -Vn CSUpscaleBilateral5x5SmartSPIRV32 -E FFX_CACAO_UpscaleBilateral5x5Smart ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOUpscaleBilateral5x5NonSmart_32.h -Vn CSUpscaleBilateral5x5NonSmartSPIRV32 -E FFX_CACAO_UpscaleBilateral5x5NonSmart ffx_cacao.hlsl
|
||||||
|
%cauldron_dxc_32% -Fh PrecompiledShadersSPIRV/CACAOUpscaleBilateral5x5Half_32.h -Vn CSUpscaleBilateral5x5HalfSPIRV32 -E FFX_CACAO_UpscaleBilateral5x5Half ffx_cacao.hlsl
|
||||||
|
|
||||||
|
popd
|
||||||
@@ -0,0 +1,263 @@
|
|||||||
|
// Modifications Copyright © 2021. Advanced Micro Devices, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (c) 2016, Intel Corporation
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
|
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is 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 Software.
|
||||||
|
// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// File changes (yyyy-mm-dd)
|
||||||
|
// 2016-09-07: filip.strugar@intel.com: first commit
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "ffx_cacao.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h> // cos, sin
|
||||||
|
#include <string.h> // memcpy
|
||||||
|
#include <stdio.h> // snprintf
|
||||||
|
|
||||||
|
// Define symbol to enable DirectX debug markers created using Cauldron
|
||||||
|
#define FFX_CACAO_ENABLE_CAULDRON_DEBUG
|
||||||
|
|
||||||
|
#define FFX_CACAO_ASSERT(exp) assert(exp)
|
||||||
|
#define FFX_CACAO_ARRAY_SIZE(xs) (sizeof(xs)/sizeof(xs[0]))
|
||||||
|
#define FFX_CACAO_COS(x) cosf(x)
|
||||||
|
#define FFX_CACAO_SIN(x) sinf(x)
|
||||||
|
#define FFX_CACAO_MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||||
|
#define FFX_CACAO_MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||||
|
#define FFX_CACAO_CLAMP(value, lower, upper) FFX_CACAO_MIN(FFX_CACAO_MAX(value, lower), upper)
|
||||||
|
#define FFX_CACAO_OFFSET_OF(T, member) (size_t)(&(((T*)0)->member))
|
||||||
|
|
||||||
|
#define MATRIX_ROW_MAJOR_ORDER 1
|
||||||
|
static const FFX_CACAO_Matrix4x4 FFX_CACAO_IDENTITY_MATRIX = {
|
||||||
|
{ { 1.0f, 0.0f, 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 0.0f, 1.0f, 0.0f },
|
||||||
|
{ 0.0f, 0.0f, 0.0f, 1.0f } }
|
||||||
|
};
|
||||||
|
|
||||||
|
void FFX_CACAO_UpdateBufferSizeInfo(uint32_t width, uint32_t height, FFX_CACAO_Bool useDownsampledSsao, FFX_CACAO_BufferSizeInfo* bsi)
|
||||||
|
{
|
||||||
|
uint32_t halfWidth = (width + 1) / 2;
|
||||||
|
uint32_t halfHeight = (height + 1) / 2;
|
||||||
|
uint32_t quarterWidth = (halfWidth + 1) / 2;
|
||||||
|
uint32_t quarterHeight = (halfHeight + 1) / 2;
|
||||||
|
uint32_t eighthWidth = (quarterWidth + 1) / 2;
|
||||||
|
uint32_t eighthHeight = (quarterHeight + 1) / 2;
|
||||||
|
|
||||||
|
uint32_t depthBufferWidth = width;
|
||||||
|
uint32_t depthBufferHeight = height;
|
||||||
|
uint32_t depthBufferHalfWidth = halfWidth;
|
||||||
|
uint32_t depthBufferHalfHeight = halfHeight;
|
||||||
|
uint32_t depthBufferQuarterWidth = quarterWidth;
|
||||||
|
uint32_t depthBufferQuarterHeight = quarterHeight;
|
||||||
|
|
||||||
|
uint32_t depthBufferXOffset = 0;
|
||||||
|
uint32_t depthBufferYOffset = 0;
|
||||||
|
uint32_t depthBufferHalfXOffset = 0;
|
||||||
|
uint32_t depthBufferHalfYOffset = 0;
|
||||||
|
uint32_t depthBufferQuarterXOffset = 0;
|
||||||
|
uint32_t depthBufferQuarterYOffset = 0;
|
||||||
|
|
||||||
|
bsi->inputOutputBufferWidth = width;
|
||||||
|
bsi->inputOutputBufferHeight = height;
|
||||||
|
bsi->depthBufferXOffset = depthBufferXOffset;
|
||||||
|
bsi->depthBufferYOffset = depthBufferYOffset;
|
||||||
|
bsi->depthBufferWidth = depthBufferWidth;
|
||||||
|
bsi->depthBufferHeight = depthBufferHeight;
|
||||||
|
|
||||||
|
if (useDownsampledSsao)
|
||||||
|
{
|
||||||
|
bsi->ssaoBufferWidth = quarterWidth;
|
||||||
|
bsi->ssaoBufferHeight = quarterHeight;
|
||||||
|
bsi->deinterleavedDepthBufferXOffset = depthBufferQuarterXOffset;
|
||||||
|
bsi->deinterleavedDepthBufferYOffset = depthBufferQuarterYOffset;
|
||||||
|
bsi->deinterleavedDepthBufferWidth = depthBufferQuarterWidth;
|
||||||
|
bsi->deinterleavedDepthBufferHeight = depthBufferQuarterHeight;
|
||||||
|
bsi->importanceMapWidth = eighthWidth;
|
||||||
|
bsi->importanceMapHeight = eighthHeight;
|
||||||
|
bsi->downsampledSsaoBufferWidth = halfWidth;
|
||||||
|
bsi->downsampledSsaoBufferHeight = halfHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bsi->ssaoBufferWidth = halfWidth;
|
||||||
|
bsi->ssaoBufferHeight = halfHeight;
|
||||||
|
bsi->deinterleavedDepthBufferXOffset = depthBufferHalfXOffset;
|
||||||
|
bsi->deinterleavedDepthBufferYOffset = depthBufferHalfYOffset;
|
||||||
|
bsi->deinterleavedDepthBufferWidth = depthBufferHalfWidth;
|
||||||
|
bsi->deinterleavedDepthBufferHeight = depthBufferHalfHeight;
|
||||||
|
bsi->importanceMapWidth = quarterWidth;
|
||||||
|
bsi->importanceMapHeight = quarterHeight;
|
||||||
|
bsi->downsampledSsaoBufferWidth = 1;
|
||||||
|
bsi->downsampledSsaoBufferHeight = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_UpdateConstants(FFX_CACAO_Constants* consts, const FFX_CACAO_Settings* settings, const FFX_CACAO_BufferSizeInfo* bufferSizeInfo, const FFX_CACAO_Matrix4x4* proj, const FFX_CACAO_Matrix4x4* normalsToView)
|
||||||
|
{
|
||||||
|
consts->BilateralSigmaSquared = settings->bilateralSigmaSquared;
|
||||||
|
consts->BilateralSimilarityDistanceSigma = settings->bilateralSimilarityDistanceSigma;
|
||||||
|
|
||||||
|
if (settings->generateNormals)
|
||||||
|
{
|
||||||
|
consts->NormalsWorldToViewspaceMatrix = FFX_CACAO_IDENTITY_MATRIX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
consts->NormalsWorldToViewspaceMatrix = *normalsToView;
|
||||||
|
}
|
||||||
|
|
||||||
|
// used to get average load per pixel; 9.0 is there to compensate for only doing every 9th InterlockedAdd in PSPostprocessImportanceMapB for performance reasons
|
||||||
|
consts->LoadCounterAvgDiv = 9.0f / (float)(bufferSizeInfo->importanceMapWidth * bufferSizeInfo->importanceMapHeight * 255.0);
|
||||||
|
|
||||||
|
float depthLinearizeMul = (MATRIX_ROW_MAJOR_ORDER) ? (-proj->elements[3][2]) : (-proj->elements[2][3]); // float depthLinearizeMul = ( clipFar * clipNear ) / ( clipFar - clipNear );
|
||||||
|
float depthLinearizeAdd = (MATRIX_ROW_MAJOR_ORDER) ? (proj->elements[2][2]) : (proj->elements[2][2]); // float depthLinearizeAdd = clipFar / ( clipFar - clipNear );
|
||||||
|
// correct the handedness issue. need to make sure this below is correct, but I think it is.
|
||||||
|
if (depthLinearizeMul * depthLinearizeAdd < 0)
|
||||||
|
depthLinearizeAdd = -depthLinearizeAdd;
|
||||||
|
consts->DepthUnpackConsts[0] = depthLinearizeMul;
|
||||||
|
consts->DepthUnpackConsts[1] = depthLinearizeAdd;
|
||||||
|
|
||||||
|
float tanHalfFOVY = 1.0f / proj->elements[1][1]; // = tanf( drawContext.Camera.GetYFOV( ) * 0.5f );
|
||||||
|
float tanHalfFOVX = 1.0F / proj->elements[0][0]; // = tanHalfFOVY * drawContext.Camera.GetAspect( );
|
||||||
|
consts->CameraTanHalfFOV[0] = tanHalfFOVX;
|
||||||
|
consts->CameraTanHalfFOV[1] = tanHalfFOVY;
|
||||||
|
|
||||||
|
consts->NDCToViewMul[0] = consts->CameraTanHalfFOV[0] * 2.0f;
|
||||||
|
consts->NDCToViewMul[1] = consts->CameraTanHalfFOV[1] * -2.0f;
|
||||||
|
consts->NDCToViewAdd[0] = consts->CameraTanHalfFOV[0] * -1.0f;
|
||||||
|
consts->NDCToViewAdd[1] = consts->CameraTanHalfFOV[1] * 1.0f;
|
||||||
|
|
||||||
|
float ratio = ((float)bufferSizeInfo->inputOutputBufferWidth) / ((float)bufferSizeInfo->depthBufferWidth);
|
||||||
|
float border = (1.0f - ratio) / 2.0f;
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
consts->DepthBufferUVToViewMul[i] = consts->NDCToViewMul[i] / ratio;
|
||||||
|
consts->DepthBufferUVToViewAdd[i] = consts->NDCToViewAdd[i] - consts->NDCToViewMul[i] * border / ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
consts->EffectRadius = FFX_CACAO_CLAMP(settings->radius, 0.0f, 100000.0f);
|
||||||
|
consts->EffectShadowStrength = FFX_CACAO_CLAMP(settings->shadowMultiplier * 4.3f, 0.0f, 10.0f);
|
||||||
|
consts->EffectShadowPow = FFX_CACAO_CLAMP(settings->shadowPower, 0.0f, 10.0f);
|
||||||
|
consts->EffectShadowClamp = FFX_CACAO_CLAMP(settings->shadowClamp, 0.0f, 1.0f);
|
||||||
|
consts->EffectFadeOutMul = -1.0f / (settings->fadeOutTo - settings->fadeOutFrom);
|
||||||
|
consts->EffectFadeOutAdd = settings->fadeOutFrom / (settings->fadeOutTo - settings->fadeOutFrom) + 1.0f;
|
||||||
|
consts->EffectHorizonAngleThreshold = FFX_CACAO_CLAMP(settings->horizonAngleThreshold, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
// 1.2 seems to be around the best trade off - 1.0 means on-screen radius will stop/slow growing when the camera is at 1.0 distance, so, depending on FOV, basically filling up most of the screen
|
||||||
|
// This setting is viewspace-dependent and not screen size dependent intentionally, so that when you change FOV the effect stays (relatively) similar.
|
||||||
|
float effectSamplingRadiusNearLimit = (settings->radius * 1.2f);
|
||||||
|
|
||||||
|
// if the depth precision is switched to 32bit float, this can be set to something closer to 1 (0.9999 is fine)
|
||||||
|
consts->DepthPrecisionOffsetMod = 0.9992f;
|
||||||
|
|
||||||
|
// Special settings for lowest quality level - just nerf the effect a tiny bit
|
||||||
|
if (settings->qualityLevel <= FFX_CACAO_QUALITY_LOW)
|
||||||
|
{
|
||||||
|
//consts.EffectShadowStrength *= 0.9f;
|
||||||
|
effectSamplingRadiusNearLimit *= 1.50f;
|
||||||
|
|
||||||
|
if (settings->qualityLevel == FFX_CACAO_QUALITY_LOWEST)
|
||||||
|
consts->EffectRadius *= 0.8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
effectSamplingRadiusNearLimit /= tanHalfFOVY; // to keep the effect same regardless of FOV
|
||||||
|
|
||||||
|
consts->EffectSamplingRadiusNearLimitRec = 1.0f / effectSamplingRadiusNearLimit;
|
||||||
|
|
||||||
|
consts->AdaptiveSampleCountLimit = settings->adaptiveQualityLimit;
|
||||||
|
|
||||||
|
consts->NegRecEffectRadius = -1.0f / consts->EffectRadius;
|
||||||
|
|
||||||
|
consts->InvSharpness = FFX_CACAO_CLAMP(1.0f - settings->sharpness, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
consts->DetailAOStrength = settings->detailShadowStrength;
|
||||||
|
|
||||||
|
// set buffer size constants.
|
||||||
|
consts->SSAOBufferDimensions[0] = (float)bufferSizeInfo->ssaoBufferWidth;
|
||||||
|
consts->SSAOBufferDimensions[1] = (float)bufferSizeInfo->ssaoBufferHeight;
|
||||||
|
consts->SSAOBufferInverseDimensions[0] = 1.0f / ((float)bufferSizeInfo->ssaoBufferWidth);
|
||||||
|
consts->SSAOBufferInverseDimensions[1] = 1.0f / ((float)bufferSizeInfo->ssaoBufferHeight);
|
||||||
|
|
||||||
|
consts->DepthBufferDimensions[0] = (float)bufferSizeInfo->depthBufferWidth;
|
||||||
|
consts->DepthBufferDimensions[1] = (float)bufferSizeInfo->depthBufferHeight;
|
||||||
|
consts->DepthBufferInverseDimensions[0] = 1.0f / ((float)bufferSizeInfo->depthBufferWidth);
|
||||||
|
consts->DepthBufferInverseDimensions[1] = 1.0f / ((float)bufferSizeInfo->depthBufferHeight);
|
||||||
|
|
||||||
|
consts->DepthBufferOffset[0] = bufferSizeInfo->depthBufferXOffset;
|
||||||
|
consts->DepthBufferOffset[1] = bufferSizeInfo->depthBufferYOffset;
|
||||||
|
|
||||||
|
consts->InputOutputBufferDimensions[0] = (float)bufferSizeInfo->inputOutputBufferWidth;
|
||||||
|
consts->InputOutputBufferDimensions[1] = (float)bufferSizeInfo->inputOutputBufferHeight;
|
||||||
|
consts->InputOutputBufferInverseDimensions[0] = 1.0f / ((float)bufferSizeInfo->inputOutputBufferWidth);
|
||||||
|
consts->InputOutputBufferInverseDimensions[1] = 1.0f / ((float)bufferSizeInfo->inputOutputBufferHeight);
|
||||||
|
|
||||||
|
consts->ImportanceMapDimensions[0] = (float)bufferSizeInfo->importanceMapWidth;
|
||||||
|
consts->ImportanceMapDimensions[1] = (float)bufferSizeInfo->importanceMapHeight;
|
||||||
|
consts->ImportanceMapInverseDimensions[0] = 1.0f / ((float)bufferSizeInfo->importanceMapWidth);
|
||||||
|
consts->ImportanceMapInverseDimensions[1] = 1.0f / ((float)bufferSizeInfo->importanceMapHeight);
|
||||||
|
|
||||||
|
consts->DeinterleavedDepthBufferDimensions[0] = (float)bufferSizeInfo->deinterleavedDepthBufferWidth;
|
||||||
|
consts->DeinterleavedDepthBufferDimensions[1] = (float)bufferSizeInfo->deinterleavedDepthBufferHeight;
|
||||||
|
consts->DeinterleavedDepthBufferInverseDimensions[0] = 1.0f / ((float)bufferSizeInfo->deinterleavedDepthBufferWidth);
|
||||||
|
consts->DeinterleavedDepthBufferInverseDimensions[1] = 1.0f / ((float)bufferSizeInfo->deinterleavedDepthBufferHeight);
|
||||||
|
|
||||||
|
consts->DeinterleavedDepthBufferOffset[0] = (float)bufferSizeInfo->deinterleavedDepthBufferXOffset;
|
||||||
|
consts->DeinterleavedDepthBufferOffset[1] = (float)bufferSizeInfo->deinterleavedDepthBufferYOffset;
|
||||||
|
consts->DeinterleavedDepthBufferNormalisedOffset[0] = ((float)bufferSizeInfo->deinterleavedDepthBufferXOffset) / ((float)bufferSizeInfo->deinterleavedDepthBufferWidth);
|
||||||
|
consts->DeinterleavedDepthBufferNormalisedOffset[1] = ((float)bufferSizeInfo->deinterleavedDepthBufferYOffset) / ((float)bufferSizeInfo->deinterleavedDepthBufferHeight);
|
||||||
|
|
||||||
|
if (!settings->generateNormals)
|
||||||
|
{
|
||||||
|
consts->NormalsUnpackMul = 2.0f; // inputs->NormalsUnpackMul;
|
||||||
|
consts->NormalsUnpackAdd = -1.0f; // inputs->NormalsUnpackAdd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
consts->NormalsUnpackMul = 2.0f;
|
||||||
|
consts->NormalsUnpackAdd = -1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_UpdatePerPassConstants(FFX_CACAO_Constants* consts, const FFX_CACAO_Settings* settings, const FFX_CACAO_BufferSizeInfo* bufferSizeInfo, int pass)
|
||||||
|
{
|
||||||
|
consts->PerPassFullResUVOffset[0] = ((float)(pass % 2)) / (float)bufferSizeInfo->ssaoBufferWidth;
|
||||||
|
consts->PerPassFullResUVOffset[1] = ((float)(pass / 2)) / (float)bufferSizeInfo->ssaoBufferHeight;
|
||||||
|
|
||||||
|
consts->PassIndex = pass;
|
||||||
|
|
||||||
|
float additionalAngleOffset = settings->temporalSupersamplingAngleOffset; // if using temporal supersampling approach (like "Progressive Rendering Using Multi-frame Sampling" from GPU Pro 7, etc.)
|
||||||
|
float additionalRadiusScale = settings->temporalSupersamplingRadiusOffset; // if using temporal supersampling approach (like "Progressive Rendering Using Multi-frame Sampling" from GPU Pro 7, etc.)
|
||||||
|
const int subPassCount = 5;
|
||||||
|
for (int subPass = 0; subPass < subPassCount; subPass++)
|
||||||
|
{
|
||||||
|
int a = pass;
|
||||||
|
int b = subPass;
|
||||||
|
|
||||||
|
int spmap[5]{ 0, 1, 4, 3, 2 };
|
||||||
|
b = spmap[subPass];
|
||||||
|
|
||||||
|
float ca, sa;
|
||||||
|
float angle0 = ((float)a + (float)b / (float)subPassCount) * (3.1415926535897932384626433832795f) * 0.5f;
|
||||||
|
|
||||||
|
ca = FFX_CACAO_COS(angle0);
|
||||||
|
sa = FFX_CACAO_SIN(angle0);
|
||||||
|
|
||||||
|
float scale = 1.0f + (a - 1.5f + (b - (subPassCount - 1.0f) * 0.5f) / (float)subPassCount) * 0.07f;
|
||||||
|
|
||||||
|
consts->PatternRotScaleMatrices[subPass][0] = scale * ca;
|
||||||
|
consts->PatternRotScaleMatrices[subPass][1] = scale * -sa;
|
||||||
|
consts->PatternRotScaleMatrices[subPass][2] = -scale * sa;
|
||||||
|
consts->PatternRotScaleMatrices[subPass][3] = -scale * ca;
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,367 @@
|
|||||||
|
// Modifications Copyright © 2021. Advanced Micro Devices, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (c) 2016, Intel Corporation
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
|
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is 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 Software.
|
||||||
|
// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// File changes (yyyy-mm-dd)
|
||||||
|
// 2016-09-07: filip.strugar@intel.com: first commit
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef FFX_CACAO_BINDINGS_HLSL
|
||||||
|
#define FFX_CACAO_BINDINGS_HLSL
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Constants
|
||||||
|
|
||||||
|
struct FFX_CACAO_Constants
|
||||||
|
{
|
||||||
|
float2 DepthUnpackConsts;
|
||||||
|
float2 CameraTanHalfFOV;
|
||||||
|
|
||||||
|
float2 NDCToViewMul;
|
||||||
|
float2 NDCToViewAdd;
|
||||||
|
|
||||||
|
float2 DepthBufferUVToViewMul;
|
||||||
|
float2 DepthBufferUVToViewAdd;
|
||||||
|
|
||||||
|
float EffectRadius; // world (viewspace) maximum size of the shadow
|
||||||
|
float EffectShadowStrength; // global strength of the effect (0 - 5)
|
||||||
|
float EffectShadowPow;
|
||||||
|
float EffectShadowClamp;
|
||||||
|
|
||||||
|
float EffectFadeOutMul; // effect fade out from distance (ex. 25)
|
||||||
|
float EffectFadeOutAdd; // effect fade out to distance (ex. 100)
|
||||||
|
float EffectHorizonAngleThreshold; // limit errors on slopes and caused by insufficient geometry tessellation (0.05 to 0.5)
|
||||||
|
float EffectSamplingRadiusNearLimitRec; // if viewspace pixel closer than this, don't enlarge shadow sampling radius anymore (makes no sense to grow beyond some distance, not enough samples to cover everything, so just limit the shadow growth; could be SSAOSettingsFadeOutFrom * 0.1 or less)
|
||||||
|
|
||||||
|
float DepthPrecisionOffsetMod;
|
||||||
|
float NegRecEffectRadius; // -1.0 / EffectRadius
|
||||||
|
float LoadCounterAvgDiv; // 1.0 / ( halfDepthMip[SSAO_DEPTH_MIP_LEVELS-1].sizeX * halfDepthMip[SSAO_DEPTH_MIP_LEVELS-1].sizeY )
|
||||||
|
float AdaptiveSampleCountLimit;
|
||||||
|
|
||||||
|
float InvSharpness;
|
||||||
|
int PassIndex;
|
||||||
|
float BilateralSigmaSquared;
|
||||||
|
float BilateralSimilarityDistanceSigma;
|
||||||
|
|
||||||
|
float4 PatternRotScaleMatrices[5];
|
||||||
|
|
||||||
|
float NormalsUnpackMul;
|
||||||
|
float NormalsUnpackAdd;
|
||||||
|
float DetailAOStrength;
|
||||||
|
float Dummy0;
|
||||||
|
|
||||||
|
float2 SSAOBufferDimensions;
|
||||||
|
float2 SSAOBufferInverseDimensions;
|
||||||
|
|
||||||
|
float2 DepthBufferDimensions;
|
||||||
|
float2 DepthBufferInverseDimensions;
|
||||||
|
|
||||||
|
int2 DepthBufferOffset;
|
||||||
|
float2 PerPassFullResUVOffset;
|
||||||
|
|
||||||
|
float2 OutputBufferDimensions;
|
||||||
|
float2 OutputBufferInverseDimensions;
|
||||||
|
|
||||||
|
float2 ImportanceMapDimensions;
|
||||||
|
float2 ImportanceMapInverseDimensions;
|
||||||
|
|
||||||
|
float2 DeinterleavedDepthBufferDimensions;
|
||||||
|
float2 DeinterleavedDepthBufferInverseDimensions;
|
||||||
|
|
||||||
|
float2 DeinterleavedDepthBufferOffset;
|
||||||
|
float2 DeinterleavedDepthBufferNormalisedOffset;
|
||||||
|
|
||||||
|
float4x4 NormalsWorldToViewspaceMatrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
cbuffer SSAOConstantsBuffer : register(b0)
|
||||||
|
{
|
||||||
|
FFX_CACAO_Constants g_FFX_CACAO_Consts;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Samplers
|
||||||
|
|
||||||
|
SamplerState g_PointClampSampler : register(s0);
|
||||||
|
SamplerState g_PointMirrorSampler : register(s1);
|
||||||
|
SamplerState g_LinearClampSampler : register(s2);
|
||||||
|
SamplerState g_ViewspaceDepthTapSampler : register(s3);
|
||||||
|
SamplerState g_RealPointClampSampler : register(s4);
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Clear Load Counter
|
||||||
|
|
||||||
|
RWTexture1D<uint> g_ClearLoadCounter_LoadCounter : register(u0);
|
||||||
|
|
||||||
|
void FFX_CACAO_ClearLoadCounter_SetLoadCounter(uint val)
|
||||||
|
{
|
||||||
|
g_ClearLoadCounter_LoadCounter[0] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Edge Sensitive Blur
|
||||||
|
|
||||||
|
Texture2DArray<float2> g_EdgeSensitiveBlur_Input : register(t0);
|
||||||
|
RWTexture2DArray<float2> g_EdgeSensitiveBlur_Output : register(u0);
|
||||||
|
|
||||||
|
float2 FFX_CACAO_EdgeSensitiveBlur_SampleInputOffset(float2 uv, int2 offset)
|
||||||
|
{
|
||||||
|
return g_EdgeSensitiveBlur_Input.SampleLevel(g_PointMirrorSampler, float3(uv, 0.0f), 0.0f, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 FFX_CACAO_EdgeSensitiveBlur_SampleInput(float2 uv)
|
||||||
|
{
|
||||||
|
return g_EdgeSensitiveBlur_Input.SampleLevel(g_PointMirrorSampler, float3(uv, 0.0f), 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_EdgeSensitiveBlur_StoreOutput(int2 coord, float2 value)
|
||||||
|
{
|
||||||
|
g_EdgeSensitiveBlur_Output[int3(coord, 0)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// SSAO Generation
|
||||||
|
|
||||||
|
Texture2DArray<float> g_ViewspaceDepthSource : register(t0);
|
||||||
|
Texture2DArray<float4> g_DeinterleavedNormals : register(t1);
|
||||||
|
Texture1D<uint> g_LoadCounter : register(t2);
|
||||||
|
Texture2D<float> g_ImportanceMap : register(t3);
|
||||||
|
Texture2DArray<float2> g_FinalSSAO : register(t4);
|
||||||
|
|
||||||
|
RWTexture2DArray<float2> g_SSAOOutput : register(u0);
|
||||||
|
|
||||||
|
float FFX_CACAO_SSAOGeneration_SampleViewspaceDepthMip(float2 uv, float mip)
|
||||||
|
{
|
||||||
|
return g_ViewspaceDepthSource.SampleLevel(g_ViewspaceDepthTapSampler, float3(uv, 0.0f), mip);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 FFX_CACAO_SSAOGeneration_GatherViewspaceDepthOffset(float2 uv, int2 offset)
|
||||||
|
{
|
||||||
|
return g_ViewspaceDepthSource.GatherRed(g_PointMirrorSampler, float3(uv, 0.0f), offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint FFX_CACAO_SSAOGeneration_GetLoadCounter()
|
||||||
|
{
|
||||||
|
return g_LoadCounter[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
float FFX_CACAO_SSAOGeneration_SampleImportance(float2 uv)
|
||||||
|
{
|
||||||
|
return g_ImportanceMap.SampleLevel(g_LinearClampSampler, uv, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 FFX_CACAO_SSAOGeneration_LoadBasePassSSAOPass(int2 coord, int pass)
|
||||||
|
{
|
||||||
|
return g_FinalSSAO.Load(int4(coord, pass, 0)).xy;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 FFX_CACAO_SSAOGeneration_GetNormalPass(int2 coord, int pass)
|
||||||
|
{
|
||||||
|
return g_DeinterleavedNormals[int3(coord, pass)].xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_SSAOGeneration_StoreOutput(int2 coord, float2 val)
|
||||||
|
{
|
||||||
|
g_SSAOOutput[int3(coord, 0)] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Apply
|
||||||
|
|
||||||
|
Texture2DArray<float2> g_ApplyFinalSSAO : register(t0);
|
||||||
|
RWTexture2D<float> g_ApplyOutput : register(u0);
|
||||||
|
|
||||||
|
float FFX_CACAO_Apply_SampleSSAOUVPass(float2 uv, int pass)
|
||||||
|
{
|
||||||
|
return g_ApplyFinalSSAO.SampleLevel(g_LinearClampSampler, float3(uv, pass), 0.0f).x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 FFX_CACAO_Apply_LoadSSAOPass(int2 coord, int pass)
|
||||||
|
{
|
||||||
|
return g_ApplyFinalSSAO.Load(int4(coord, pass, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Apply_StoreOutput(int2 coord, float val)
|
||||||
|
{
|
||||||
|
g_ApplyOutput[coord] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Prepare
|
||||||
|
|
||||||
|
Texture2D<float> g_DepthIn : register(t0);
|
||||||
|
Texture2D<float4> g_PrepareNormalsFromNormalsInput : register(t0);
|
||||||
|
|
||||||
|
RWTexture2DArray<float> g_PrepareDepthsAndMips_OutMip0 : register(u0);
|
||||||
|
RWTexture2DArray<float> g_PrepareDepthsAndMips_OutMip1 : register(u1);
|
||||||
|
RWTexture2DArray<float> g_PrepareDepthsAndMips_OutMip2 : register(u2);
|
||||||
|
RWTexture2DArray<float> g_PrepareDepthsAndMips_OutMip3 : register(u3);
|
||||||
|
|
||||||
|
RWTexture2DArray<float> g_PrepareDepthsOut : register(u0);
|
||||||
|
|
||||||
|
RWTexture2DArray<float4> g_PrepareNormals_NormalOut : register(u0);
|
||||||
|
|
||||||
|
float FFX_CACAO_Prepare_SampleDepthOffset(float2 uv, int2 offset)
|
||||||
|
{
|
||||||
|
return g_DepthIn.SampleLevel(g_PointClampSampler, uv, 0.0f, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 FFX_CACAO_Prepare_GatherDepth(float2 uv)
|
||||||
|
{
|
||||||
|
return g_DepthIn.GatherRed(g_PointClampSampler, uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
float FFX_CACAO_Prepare_LoadDepth(int2 coord)
|
||||||
|
{
|
||||||
|
return g_DepthIn.Load(int3(coord, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float FFX_CACAO_Prepare_LoadDepthOffset(int2 coord, int2 offset)
|
||||||
|
{
|
||||||
|
return g_DepthIn.Load(int3(coord, 0), offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 FFX_CACAO_Prepare_GatherDepthOffset(float2 uv, int2 offset)
|
||||||
|
{
|
||||||
|
return g_DepthIn.GatherRed(g_PointClampSampler, uv, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 FFX_CACAO_Prepare_LoadNormal(int2 coord)
|
||||||
|
{
|
||||||
|
float3 normal = g_PrepareNormalsFromNormalsInput.Load(int3(coord, 0)).xyz;
|
||||||
|
normal = normal * g_FFX_CACAO_Consts.NormalsUnpackMul.xxx + g_FFX_CACAO_Consts.NormalsUnpackAdd.xxx;
|
||||||
|
normal = mul(normal, (float3x3)g_FFX_CACAO_Consts.NormalsWorldToViewspaceMatrix).xyz;
|
||||||
|
// normal = normalize(normal);
|
||||||
|
return normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Prepare_StoreDepthMip0(int2 coord, int index, float val)
|
||||||
|
{
|
||||||
|
g_PrepareDepthsAndMips_OutMip0[int3(coord, index)] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Prepare_StoreDepthMip1(int2 coord, int index, float val)
|
||||||
|
{
|
||||||
|
g_PrepareDepthsAndMips_OutMip1[int3(coord, index)] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Prepare_StoreDepthMip2(int2 coord, int index, float val)
|
||||||
|
{
|
||||||
|
g_PrepareDepthsAndMips_OutMip2[int3(coord, index)] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Prepare_StoreDepthMip3(int2 coord, int index, float val)
|
||||||
|
{
|
||||||
|
g_PrepareDepthsAndMips_OutMip3[int3(coord, index)] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Prepare_StoreDepth(int2 coord, int index, float val)
|
||||||
|
{
|
||||||
|
g_PrepareDepthsOut[int3(coord, index)] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Prepare_StoreNormal(int2 coord, int index, float3 normal)
|
||||||
|
{
|
||||||
|
g_PrepareNormals_NormalOut[int3(coord, index)] = float4(normal, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Importance Map
|
||||||
|
|
||||||
|
Texture2DArray<float2> g_ImportanceFinalSSAO : register(t0);
|
||||||
|
RWTexture2D<float> g_ImportanceOut : register(u0);
|
||||||
|
|
||||||
|
Texture2D<float> g_ImportanceAIn : register(t0);
|
||||||
|
RWTexture2D<float> g_ImportanceAOut : register(u0);
|
||||||
|
|
||||||
|
Texture2D<float> g_ImportanceBIn : register(t0);
|
||||||
|
RWTexture2D<float> g_ImportanceBOut : register(u0);
|
||||||
|
RWTexture1D<uint> g_ImportanceBLoadCounter : register(u1);
|
||||||
|
|
||||||
|
float4 FFX_CACAO_Importance_GatherSSAO(float2 uv, int index)
|
||||||
|
{
|
||||||
|
return g_ImportanceFinalSSAO.GatherRed(g_PointClampSampler, float3(uv, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Importance_StoreImportance(int2 coord, float val)
|
||||||
|
{
|
||||||
|
g_ImportanceOut[coord] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FFX_CACAO_Importance_SampleImportanceA(float2 uv)
|
||||||
|
{
|
||||||
|
return g_ImportanceAIn.SampleLevel(g_LinearClampSampler, uv, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Importance_StoreImportanceA(int2 coord, float val)
|
||||||
|
{
|
||||||
|
g_ImportanceAOut[coord] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FFX_CACAO_Importance_SampleImportanceB(float2 uv)
|
||||||
|
{
|
||||||
|
return g_ImportanceBIn.SampleLevel(g_LinearClampSampler, uv, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Importance_StoreImportanceB(int2 coord, float val)
|
||||||
|
{
|
||||||
|
g_ImportanceBOut[coord] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFX_CACAO_Importance_LoadCounterInterlockedAdd(uint val)
|
||||||
|
{
|
||||||
|
InterlockedAdd(g_ImportanceBLoadCounter[0], val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Bilateral Upscale
|
||||||
|
|
||||||
|
RWTexture2D<float> g_BilateralUpscaleOutput : register(u0);
|
||||||
|
|
||||||
|
Texture2DArray<float2> g_BilateralUpscaleInput : register(t0);
|
||||||
|
Texture2D<float> g_BilateralUpscaleDepth : register(t1);
|
||||||
|
Texture2DArray<float> g_BilateralUpscaleDownscaledDepth : register(t2);
|
||||||
|
|
||||||
|
void FFX_CACAO_BilateralUpscale_StoreOutput(int2 coord, int2 offset, float val)
|
||||||
|
{
|
||||||
|
g_BilateralUpscaleOutput[coord + offset] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FFX_CACAO_BilateralUpscale_SampleSSAOLinear(float2 uv, int index)
|
||||||
|
{
|
||||||
|
return g_BilateralUpscaleInput.SampleLevel(g_LinearClampSampler, float3(uv, index), 0).x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FFX_CACAO_BilateralUpscale_SampleSSAOPoint(float2 uv, int index)
|
||||||
|
{
|
||||||
|
return g_BilateralUpscaleInput.SampleLevel(g_PointClampSampler, float3(uv, index), 0).x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 FFX_CACAO_BilateralUpscale_LoadSSAO(int2 coord, int index)
|
||||||
|
{
|
||||||
|
return g_BilateralUpscaleInput.Load(int4(coord, index, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float FFX_CACAO_BilateralUpscale_LoadDepth(int2 coord, int2 offset)
|
||||||
|
{
|
||||||
|
return g_BilateralUpscaleDepth.Load(int3(coord, 0), offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
float FFX_CACAO_BilateralUpscale_LoadDownscaledDepth(int2 coord, int index)
|
||||||
|
{
|
||||||
|
return g_BilateralUpscaleDownscaledDepth.Load(int4(coord, index, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// Modifications Copyright © 2021. Advanced Micro Devices, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (c) 2016, Intel Corporation
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
|
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is 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 Software.
|
||||||
|
// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// File changes (yyyy-mm-dd)
|
||||||
|
// 2016-09-07: filip.strugar@intel.com: first commit
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Defines for constants common to both CACAO.cpp and CACAO.hlsl
|
||||||
|
|
||||||
|
#ifndef FFX_CACAO_DEFINES_H
|
||||||
|
#define FFX_CACAO_DEFINES_H
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Prepare
|
||||||
|
|
||||||
|
#define FFX_CACAO_PREPARE_DEPTHS_AND_MIPS_WIDTH 8
|
||||||
|
#define FFX_CACAO_PREPARE_DEPTHS_AND_MIPS_HEIGHT 8
|
||||||
|
|
||||||
|
#define FFX_CACAO_PREPARE_DEPTHS_WIDTH 8
|
||||||
|
#define FFX_CACAO_PREPARE_DEPTHS_HEIGHT 8
|
||||||
|
|
||||||
|
#define FFX_CACAO_PREPARE_DEPTHS_HALF_WIDTH 8
|
||||||
|
#define FFX_CACAO_PREPARE_DEPTHS_HALF_HEIGHT 8
|
||||||
|
|
||||||
|
#define FFX_CACAO_PREPARE_NORMALS_WIDTH 8
|
||||||
|
#define FFX_CACAO_PREPARE_NORMALS_HEIGHT 8
|
||||||
|
|
||||||
|
#define PREPARE_NORMALS_FROM_INPUT_NORMALS_WIDTH 8
|
||||||
|
#define PREPARE_NORMALS_FROM_INPUT_NORMALS_HEIGHT 8
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// SSAO Generation
|
||||||
|
|
||||||
|
#define FFX_CACAO_GENERATE_SPARSE_WIDTH 4
|
||||||
|
#define FFX_CACAO_GENERATE_SPARSE_HEIGHT 16
|
||||||
|
|
||||||
|
#define FFX_CACAO_GENERATE_WIDTH 8
|
||||||
|
#define FFX_CACAO_GENERATE_HEIGHT 8
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Importance Map
|
||||||
|
|
||||||
|
#define IMPORTANCE_MAP_WIDTH 8
|
||||||
|
#define IMPORTANCE_MAP_HEIGHT 8
|
||||||
|
|
||||||
|
#define IMPORTANCE_MAP_A_WIDTH 8
|
||||||
|
#define IMPORTANCE_MAP_A_HEIGHT 8
|
||||||
|
|
||||||
|
#define IMPORTANCE_MAP_B_WIDTH 8
|
||||||
|
#define IMPORTANCE_MAP_B_HEIGHT 8
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Edge Sensitive Blur
|
||||||
|
|
||||||
|
#define FFX_CACAO_BLUR_WIDTH 16
|
||||||
|
#define FFX_CACAO_BLUR_HEIGHT 16
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Apply
|
||||||
|
|
||||||
|
#define FFX_CACAO_APPLY_WIDTH 8
|
||||||
|
#define FFX_CACAO_APPLY_HEIGHT 8
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Bilateral Upscale
|
||||||
|
|
||||||
|
#define FFX_CACAO_BILATERAL_UPSCALE_WIDTH 8
|
||||||
|
#define FFX_CACAO_BILATERAL_UPSCALE_HEIGHT 8
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location=0)in vec3 fragColor;
|
||||||
|
layout(location=0)out vec4 f_color;
|
||||||
|
|
||||||
|
const vec3 light=normalize(vec3(4,6,8));
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
f_color=vec4(vec3(dot(fragColor,light))*.5+.5,1.);
|
||||||
|
}
|
||||||
Binary file not shown.
+777
@@ -0,0 +1,777 @@
|
|||||||
|
// Copyright (c) 2016 The vulkano developers
|
||||||
|
// Licensed under the Apache License, Version 2.0
|
||||||
|
// <LICENSE-APACHE or
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
|
||||||
|
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
|
||||||
|
// at your option. All files in the project carrying such
|
||||||
|
// notice may not be copied, modified, or distributed except
|
||||||
|
// according to those terms.
|
||||||
|
|
||||||
|
// Welcome to the triangle example!
|
||||||
|
//
|
||||||
|
// This is the only example that is entirely detailed. All the other examples avoid code
|
||||||
|
// duplication by using helper functions.
|
||||||
|
//
|
||||||
|
// This example assumes that you are already more or less familiar with graphics programming
|
||||||
|
// and that you want to learn Vulkan. This means that for example it won't go into details about
|
||||||
|
// what a vertex or a shader is.
|
||||||
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
use cgmath::{Matrix3, Matrix4, Point3, Rad, Vector3};
|
||||||
|
use obj::{LoadConfig, ObjData};
|
||||||
|
use rodio::{source::Source, Decoder, OutputStream};
|
||||||
|
use std::io::Cursor;
|
||||||
|
use std::{sync::Arc, time::Instant};
|
||||||
|
use vulkano::buffer::CpuBufferPool;
|
||||||
|
use vulkano::command_buffer::allocator::StandardCommandBufferAllocator;
|
||||||
|
use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator;
|
||||||
|
use vulkano::device::QueueFlags;
|
||||||
|
use vulkano::format::Format;
|
||||||
|
use vulkano::image::AttachmentImage;
|
||||||
|
use vulkano::memory::allocator::{MemoryAllocator, MemoryUsage, StandardMemoryAllocator};
|
||||||
|
use vulkano::pipeline::graphics::depth_stencil::DepthStencilState;
|
||||||
|
use vulkano::pipeline::graphics::rasterization::CullMode;
|
||||||
|
use vulkano::pipeline::graphics::rasterization::FrontFace::Clockwise;
|
||||||
|
use vulkano::swapchain::SwapchainPresentInfo;
|
||||||
|
use vulkano::{memory, VulkanLibrary};
|
||||||
|
|
||||||
|
use egui_winit_vulkano::Gui;
|
||||||
|
use vulkano::pipeline::StateMode::Fixed;
|
||||||
|
use vulkano::{
|
||||||
|
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||||
|
command_buffer::{
|
||||||
|
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||||
|
},
|
||||||
|
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||||
|
device::{
|
||||||
|
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||||
|
},
|
||||||
|
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
||||||
|
impl_vertex,
|
||||||
|
instance::{Instance, InstanceCreateInfo},
|
||||||
|
pipeline::{
|
||||||
|
graphics::{
|
||||||
|
input_assembly::InputAssemblyState,
|
||||||
|
rasterization::RasterizationState,
|
||||||
|
vertex_input::BuffersDefinition,
|
||||||
|
viewport::{Viewport, ViewportState},
|
||||||
|
},
|
||||||
|
GraphicsPipeline, Pipeline, PipelineBindPoint,
|
||||||
|
},
|
||||||
|
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||||
|
swapchain::{
|
||||||
|
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
|
||||||
|
},
|
||||||
|
sync::{self, FlushError, GpuFuture},
|
||||||
|
};
|
||||||
|
use vulkano_win::VkSurfaceBuild;
|
||||||
|
use winit::{
|
||||||
|
event::{Event, WindowEvent},
|
||||||
|
event_loop::{ControlFlow, EventLoop},
|
||||||
|
window::{Window, WindowBuilder},
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// The first step of any Vulkan program is to create an instance.
|
||||||
|
//
|
||||||
|
// When we create an instance, we have to pass a list of extensions that we want to enable.
|
||||||
|
//
|
||||||
|
// All the window-drawing functionalities are part of non-core extensions that we need
|
||||||
|
// to enable manually. To do so, we ask the `vulkano_win` crate for the list of extensions
|
||||||
|
// required to draw to a window.
|
||||||
|
let library = VulkanLibrary::new().unwrap();
|
||||||
|
let required_extensions = vulkano_win::required_extensions(&library);
|
||||||
|
|
||||||
|
// Now creating the instance.
|
||||||
|
let instance = Instance::new(
|
||||||
|
library,
|
||||||
|
InstanceCreateInfo {
|
||||||
|
enabled_extensions: required_extensions,
|
||||||
|
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
|
||||||
|
enumerate_portability: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// The objective of this example is to draw a triangle on a window. To do so, we first need to
|
||||||
|
// create the window.
|
||||||
|
//
|
||||||
|
// This is done by creating a `WindowBuilder` from the `winit` crate, then calling the
|
||||||
|
// `build_vk_surface` method provided by the `VkSurfaceBuild` trait from `vulkano_win`. If you
|
||||||
|
// ever get an error about `build_vk_surface` being undefined in one of your projects, this
|
||||||
|
// probably means that you forgot to import this trait.
|
||||||
|
//
|
||||||
|
// This returns a `vulkano::swapchain::Surface` object that contains both a cross-platform winit
|
||||||
|
// window and a cross-platform Vulkan surface that represents the surface of the window.
|
||||||
|
let event_loop = EventLoop::new();
|
||||||
|
let surface = WindowBuilder::new()
|
||||||
|
.with_title("horizontally spinning bunny")
|
||||||
|
.build_vk_surface(&event_loop, instance.clone())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Choose device extensions that we're going to use.
|
||||||
|
// In order to present images to a surface, we need a `Swapchain`, which is provided by the
|
||||||
|
// `khr_swapchain` extension.
|
||||||
|
let device_extensions = DeviceExtensions {
|
||||||
|
khr_swapchain: true,
|
||||||
|
..DeviceExtensions::empty()
|
||||||
|
};
|
||||||
|
|
||||||
|
// We then choose which physical device to use. First, we enumerate all the available physical
|
||||||
|
// devices, then apply filters to narrow them down to those that can support our needs.
|
||||||
|
let (physical_device, queue_family_index) = instance
|
||||||
|
.enumerate_physical_devices()
|
||||||
|
.unwrap()
|
||||||
|
.filter(|p| {
|
||||||
|
// Some devices may not support the extensions or features that your application, or
|
||||||
|
// report properties and limits that are not sufficient for your application. These
|
||||||
|
// should be filtered out here.
|
||||||
|
p.supported_extensions().contains(&device_extensions)
|
||||||
|
})
|
||||||
|
.filter_map(|p| {
|
||||||
|
// For each physical device, we try to find a suitable queue family that will execute
|
||||||
|
// our draw commands.
|
||||||
|
//
|
||||||
|
// Devices can provide multiple queues to run commands in parallel (for example a draw
|
||||||
|
// queue and a compute queue), similar to CPU threads. This is something you have to
|
||||||
|
// have to manage manually in Vulkan. Queues of the same type belong to the same
|
||||||
|
// queue family.
|
||||||
|
//
|
||||||
|
// Here, we look for a single queue family that is suitable for our purposes. In a
|
||||||
|
// real-life application, you may want to use a separate dedicated transfer queue to
|
||||||
|
// handle data transfers in parallel with graphics operations. You may also need a
|
||||||
|
// separate queue for compute operations, if your application uses those.
|
||||||
|
p.queue_family_properties()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.position(|(i, q)| {
|
||||||
|
// We select a queue family that supports graphics operations. When drawing to
|
||||||
|
// a window surface, as we do in this example, we also need to check that queues
|
||||||
|
// in this queue family are capable of presenting images to the surface.
|
||||||
|
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||||
|
})
|
||||||
|
// The code here searches for the first queue family that is suitable. If none is
|
||||||
|
// found, `None` is returned to `filter_map`, which disqualifies this physical
|
||||||
|
// device.
|
||||||
|
.map(|i| (p, i as u32))
|
||||||
|
})
|
||||||
|
// All the physical devices that pass the filters above are suitable for the application.
|
||||||
|
// However, not every device is equal, some are preferred over others. Now, we assign
|
||||||
|
// each physical device a score, and pick the device with the
|
||||||
|
// lowest ("best") score.
|
||||||
|
//
|
||||||
|
// In this example, we simply select the best-scoring device to use in the application.
|
||||||
|
// In a real-life setting, you may want to use the best-scoring device only as a
|
||||||
|
// "default" or "recommended" device, and let the user choose the device themselves.
|
||||||
|
.min_by_key(|(p, _)| {
|
||||||
|
// We assign a lower score to device types that are likely to be faster/better.
|
||||||
|
match p.properties().device_type {
|
||||||
|
PhysicalDeviceType::DiscreteGpu => 0,
|
||||||
|
PhysicalDeviceType::IntegratedGpu => 1,
|
||||||
|
PhysicalDeviceType::VirtualGpu => 2,
|
||||||
|
PhysicalDeviceType::Cpu => 3,
|
||||||
|
PhysicalDeviceType::Other => 4,
|
||||||
|
_ => 5,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.expect("No suitable physical device found");
|
||||||
|
|
||||||
|
// Some little debug infos.
|
||||||
|
println!(
|
||||||
|
"Using device: {} (type: {:?})",
|
||||||
|
physical_device.properties().device_name,
|
||||||
|
physical_device.properties().device_type,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Now initializing the device. This is probably the most important object of Vulkan.
|
||||||
|
//
|
||||||
|
// The iterator of created queues is returned by the function alongside the device.
|
||||||
|
let (device, mut queues) = Device::new(
|
||||||
|
// Which physical device to connect to.
|
||||||
|
physical_device,
|
||||||
|
DeviceCreateInfo {
|
||||||
|
// A list of optional features and extensions that our program needs to work correctly.
|
||||||
|
// Some parts of the Vulkan specs are optional and must be enabled manually at device
|
||||||
|
// creation. In this example the only thing we are going to need is the `khr_swapchain`
|
||||||
|
// extension that allows us to draw to a window.
|
||||||
|
enabled_extensions: device_extensions,
|
||||||
|
|
||||||
|
// The list of queues that we are going to use. Here we only use one queue, from the
|
||||||
|
// previously chosen queue family.
|
||||||
|
queue_create_infos: vec![QueueCreateInfo {
|
||||||
|
queue_family_index,
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.expect("Unable to initialize device");
|
||||||
|
|
||||||
|
// Since we can request multiple queues, the `queues` variable is in fact an iterator. We
|
||||||
|
// only use one queue in this example, so we just retrieve the first and only element of the
|
||||||
|
// iterator.
|
||||||
|
let queue = queues.next().expect("Unable to retrieve queues");
|
||||||
|
|
||||||
|
// Create an egui GUI
|
||||||
|
let mut gui = Gui::new(&event_loop, surface.clone(), None, queue.clone(), false);
|
||||||
|
|
||||||
|
// Before we can draw on the surface, we have to create what is called a swapchain. Creating
|
||||||
|
// a swapchain allocates the color buffers that will contain the image that will ultimately
|
||||||
|
// be visible on the screen. These images are returned alongside the swapchain.
|
||||||
|
let (mut swapchain, images) = {
|
||||||
|
// Querying the capabilities of the surface. When we create the swapchain we can only
|
||||||
|
// pass values that are allowed by the capabilities.
|
||||||
|
let surface_capabilities = device
|
||||||
|
.physical_device()
|
||||||
|
.surface_capabilities(&surface, Default::default())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Choosing the internal format that the images will have.
|
||||||
|
let image_format = Some(
|
||||||
|
device
|
||||||
|
.physical_device()
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
let window = surface.object().unwrap().downcast_ref::<Window>().unwrap();
|
||||||
|
|
||||||
|
// Please take a look at the docs for the meaning of the parameters we didn't mention.
|
||||||
|
Swapchain::new(
|
||||||
|
device.clone(),
|
||||||
|
surface.clone(),
|
||||||
|
SwapchainCreateInfo {
|
||||||
|
min_image_count: 3
|
||||||
|
.max(surface_capabilities.min_image_count)
|
||||||
|
.min(surface_capabilities.max_image_count.unwrap_or(u32::MAX)),
|
||||||
|
|
||||||
|
image_format,
|
||||||
|
// The dimensions of the window, only used to initially setup the swapchain.
|
||||||
|
// NOTE:
|
||||||
|
// On some drivers the swapchain dimensions are specified by
|
||||||
|
// `surface_capabilities.current_extent` and the swapchain size must use these
|
||||||
|
// dimensions.
|
||||||
|
// These dimensions are always the same as the window dimensions.
|
||||||
|
//
|
||||||
|
// However, other drivers don't specify a value, i.e.
|
||||||
|
// `surface_capabilities.current_extent` is `None`. These drivers will allow
|
||||||
|
// anything, but the only sensible value is the window
|
||||||
|
// dimensions.
|
||||||
|
//
|
||||||
|
// Both of these cases need the swapchain to use the window dimensions, so we just
|
||||||
|
// use that.
|
||||||
|
image_extent: window.inner_size().into(),
|
||||||
|
|
||||||
|
image_usage: ImageUsage {
|
||||||
|
color_attachment: true,
|
||||||
|
..ImageUsage::empty()
|
||||||
|
},
|
||||||
|
|
||||||
|
// The alpha mode indicates how the alpha value of the final image will behave. For
|
||||||
|
// example, you can choose whether the window will be opaque or transparent.
|
||||||
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
const OBJ: &[u8] = include_bytes!("bunny.obj");
|
||||||
|
|
||||||
|
let buny = ObjData::load_buf_with_config(OBJ, LoadConfig::default()).unwrap();
|
||||||
|
|
||||||
|
let polys = &buny.objects[0].groups[0].polys;
|
||||||
|
|
||||||
|
let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
|
||||||
|
|
||||||
|
// We now create a buffer that will store the shape of our triangle.
|
||||||
|
// We use #[repr(C)] here to force rustc to not do anything funky with our data, although for this
|
||||||
|
// particular example, it doesn't actually change the in-memory representation.
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||||
|
struct Vertex {
|
||||||
|
position: [f32; 3],
|
||||||
|
normal: [f32; 3],
|
||||||
|
}
|
||||||
|
impl_vertex!(Vertex, position, normal);
|
||||||
|
|
||||||
|
let vertices = polys
|
||||||
|
.iter()
|
||||||
|
.flat_map(|p| {
|
||||||
|
p.0.iter()
|
||||||
|
.map(|v| Vertex {
|
||||||
|
position: buny.position[v.0],
|
||||||
|
normal: v
|
||||||
|
.2
|
||||||
|
.and_then(|vt| Some(buny.normal[vt]))
|
||||||
|
.unwrap_or([0.0, 0.0, 0.0]),
|
||||||
|
})
|
||||||
|
.collect::<Vec<Vertex>>()
|
||||||
|
})
|
||||||
|
.collect::<Vec<Vertex>>();
|
||||||
|
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||||
|
&memory_allocator,
|
||||||
|
BufferUsage {
|
||||||
|
vertex_buffer: true,
|
||||||
|
..BufferUsage::empty()
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
vertices,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// The next step is to create the shaders.
|
||||||
|
//
|
||||||
|
// The raw shader creation API provided by the vulkano library is unsafe for various
|
||||||
|
// reasons, so The `shader!` macro provides a way to generate a Rust module from GLSL
|
||||||
|
// source - in the example below, the source is provided as a string input directly to
|
||||||
|
// the shader, but a path to a source file can be provided as well. Note that the user
|
||||||
|
// must specify the type of shader (e.g., "vertex," "fragment, etc.") using the `ty`
|
||||||
|
// option of the macro.
|
||||||
|
//
|
||||||
|
// The module generated by the `shader!` macro includes a `load` function which loads
|
||||||
|
// the shader using an input logical device. The module also includes type definitions
|
||||||
|
// for layout structures defined in the shader source, for example, uniforms and push
|
||||||
|
// constants.
|
||||||
|
//
|
||||||
|
// A more detailed overview of what the `shader!` macro generates can be found in the
|
||||||
|
// `vulkano-shaders` crate docs. You can view them at https://docs.rs/vulkano-shaders/
|
||||||
|
mod vs {
|
||||||
|
vulkano_shaders::shader! {
|
||||||
|
ty: "vertex",
|
||||||
|
src: "
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 position;
|
||||||
|
layout(location = 1) in vec3 normal;
|
||||||
|
|
||||||
|
layout(location = 0) out vec3 v_normal;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PushConstantData {
|
||||||
|
mat4 world;
|
||||||
|
mat4 view;
|
||||||
|
mat4 proj;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
mat4 worldview = pc.view * pc.world;
|
||||||
|
v_normal = normalize(transpose(inverse(mat3(worldview))) * normal);
|
||||||
|
gl_Position = pc.proj * worldview * vec4(position*1000.0, 1.0);
|
||||||
|
}
|
||||||
|
",
|
||||||
|
types_meta: {
|
||||||
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Zeroable, Pod, Debug)]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod fs {
|
||||||
|
vulkano_shaders::shader! {
|
||||||
|
ty: "fragment",
|
||||||
|
path: "src/frag.glsl"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let vs = vs::load(device.clone()).unwrap();
|
||||||
|
let fs = fs::load(device.clone()).unwrap();
|
||||||
|
|
||||||
|
/*let uniform_buffer =
|
||||||
|
CpuBufferPool::<vs::ty::PushConstantData>::uniform_buffer(memory_allocator);*/
|
||||||
|
|
||||||
|
// At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL
|
||||||
|
// implicitly does a lot of computation whenever you draw. In Vulkan, you have to do all this
|
||||||
|
// manually.
|
||||||
|
|
||||||
|
// The next step is to create a *render pass*, which is an object that describes where the
|
||||||
|
// output of the graphics pipeline will go. It describes the layout of the images
|
||||||
|
// where the colors, depth and/or stencil information will be written.
|
||||||
|
let render_pass = vulkano::single_pass_renderpass!(
|
||||||
|
device.clone(),
|
||||||
|
attachments: {
|
||||||
|
// `color` is a custom name we give to the first and only attachment.
|
||||||
|
color: {
|
||||||
|
// `load: Clear` means that we ask the GPU to clear the content of this
|
||||||
|
// attachment at the start of the drawing.
|
||||||
|
load: Clear,
|
||||||
|
// `store: Store` means that we ask the GPU to store the output of the draw
|
||||||
|
// in the actual image. We could also ask it to discard the result.
|
||||||
|
store: Store,
|
||||||
|
// `format: <ty>` indicates the type of the format of the image. This has to
|
||||||
|
// be one of the types of the `vulkano::format` module (or alternatively one
|
||||||
|
// of your structs that implements the `FormatDesc` trait). Here we use the
|
||||||
|
// same format as the swapchain.
|
||||||
|
format: swapchain.image_format(),
|
||||||
|
// `samples: 1` means that we ask the GPU to use one sample to determine the value
|
||||||
|
// of each pixel in the color attachment. We could use a larger value (multisampling)
|
||||||
|
// for antialiasing. An example of this can be found in msaa-renderpass.rs.
|
||||||
|
samples: 1,
|
||||||
|
},
|
||||||
|
depth: {
|
||||||
|
load: Clear,
|
||||||
|
store: DontCare,
|
||||||
|
format: Format::D16_UNORM,
|
||||||
|
samples: 1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pass: {
|
||||||
|
// We use the attachment named `color` as the one and only color attachment.
|
||||||
|
color: [color],
|
||||||
|
// No depth-stencil attachment is indicated with empty brackets.
|
||||||
|
depth_stencil: {depth}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Before we draw we have to create what is called a pipeline. This is similar to an OpenGL
|
||||||
|
// program, but much more specific.
|
||||||
|
let pipeline = GraphicsPipeline::start()
|
||||||
|
// We have to indicate which subpass of which render pass this pipeline is going to be used
|
||||||
|
// in. The pipeline will only be usable from this particular subpass.
|
||||||
|
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
|
||||||
|
// We need to indicate the layout of the vertices.
|
||||||
|
.vertex_input_state(BuffersDefinition::new().vertex::<Vertex>())
|
||||||
|
// The content of the vertex buffer describes a list of triangles.
|
||||||
|
.input_assembly_state(InputAssemblyState::new())
|
||||||
|
// A Vulkan shader can in theory contain multiple entry points, so we have to specify
|
||||||
|
// which one.
|
||||||
|
.vertex_shader(vs.entry_point("main").unwrap(), ())
|
||||||
|
// Use a resizable viewport set to draw over the entire window
|
||||||
|
.viewport_state(ViewportState::viewport_dynamic_scissor_irrelevant())
|
||||||
|
// See `vertex_shader`.
|
||||||
|
.fragment_shader(fs.entry_point("main").unwrap(), ())
|
||||||
|
.depth_stencil_state(DepthStencilState::simple_depth_test())
|
||||||
|
.rasterization_state(RasterizationState {
|
||||||
|
front_face: Fixed(Clockwise),
|
||||||
|
cull_mode: Fixed(CullMode::Back),
|
||||||
|
..RasterizationState::default()
|
||||||
|
})
|
||||||
|
// Now that our builder is filled, we call `build()` to obtain an actual pipeline.
|
||||||
|
.build(device.clone())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Dynamic viewports allow us to recreate just the viewport when the window is resized
|
||||||
|
// Otherwise we would have to recreate the whole pipeline.
|
||||||
|
let mut viewport = Viewport {
|
||||||
|
origin: [0.0, 0.0],
|
||||||
|
dimensions: [0.0, 0.0],
|
||||||
|
depth_range: 0.0..1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// The render pass we created above only describes the layout of our framebuffers. Before we
|
||||||
|
// can draw we also need to create the actual framebuffers.
|
||||||
|
//
|
||||||
|
// Since we need to draw to multiple images, we are going to create a different framebuffer for
|
||||||
|
// each image.
|
||||||
|
let mut framebuffers = window_size_dependent_setup(
|
||||||
|
&memory_allocator,
|
||||||
|
&images,
|
||||||
|
render_pass.clone(),
|
||||||
|
&mut viewport,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Before we can start creating and recording command buffers, we need a way of allocating
|
||||||
|
// them. Vulkano provides a command buffer allocator, which manages raw Vulkan command pools
|
||||||
|
// underneath and provides a safe interface for them.
|
||||||
|
let command_buffer_allocator =
|
||||||
|
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||||
|
|
||||||
|
// Initialization is finally finished!
|
||||||
|
|
||||||
|
// In some situations, the swapchain will become invalid by itself. This includes for example
|
||||||
|
// when the window is resized (as the images of the swapchain will no longer match the
|
||||||
|
// window's) or, on Android, when the application went to the background and goes back to the
|
||||||
|
// foreground.
|
||||||
|
//
|
||||||
|
// In this situation, acquiring a swapchain image or presenting it will return an error.
|
||||||
|
// Rendering to an image of that swapchain will not produce any error, but may or may not work.
|
||||||
|
// To continue rendering, we need to recreate the swapchain by creating a new swapchain.
|
||||||
|
// Here, we remember that we need to do this for the next loop iteration.
|
||||||
|
let mut recreate_swapchain = false;
|
||||||
|
|
||||||
|
// In the loop below we are going to submit commands to the GPU. Submitting a command produces
|
||||||
|
// an object that implements the `GpuFuture` trait, which holds the resources for as long as
|
||||||
|
// they are in use by the GPU.
|
||||||
|
//
|
||||||
|
// Destroying the `GpuFuture` blocks until the GPU is finished executing it. In order to avoid
|
||||||
|
// that, we store the submission of the previous frame here.
|
||||||
|
let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
|
||||||
|
|
||||||
|
// Get a output stream handle to the default physical sound device
|
||||||
|
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
|
||||||
|
// Load a sound from a file, using a path relative to Cargo.toml
|
||||||
|
let freebird = Cursor::new(include_bytes!("freebird.mp3"));
|
||||||
|
// Decode that sound file into a source
|
||||||
|
let source = Decoder::new(freebird).unwrap().repeat_infinite();
|
||||||
|
// Play the sound directly on the device
|
||||||
|
stream_handle.play_raw(source.convert_samples()).unwrap();
|
||||||
|
|
||||||
|
let rotation_start = Instant::now();
|
||||||
|
|
||||||
|
//let descriptor_set_allocator = StandardDescriptorSetAllocator::new(device.clone());
|
||||||
|
|
||||||
|
event_loop.run(move |event, _, control_flow| {
|
||||||
|
match event {
|
||||||
|
Event::WindowEvent {
|
||||||
|
event: WindowEvent::CloseRequested,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
*control_flow = ControlFlow::Exit;
|
||||||
|
}
|
||||||
|
Event::WindowEvent {
|
||||||
|
event: WindowEvent::Resized(_),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
recreate_swapchain = true;
|
||||||
|
}
|
||||||
|
Event::RedrawEventsCleared => {
|
||||||
|
// Do not draw frame when screen dimensions are zero.
|
||||||
|
// On Windows, this can occur from minimizing the application.
|
||||||
|
let window = surface.object().unwrap().downcast_ref::<Window>().unwrap();
|
||||||
|
let dimensions = window.inner_size();
|
||||||
|
if dimensions.width == 0 || dimensions.height == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is important to call this function from time to time, otherwise resources will keep
|
||||||
|
// accumulating and you will eventually reach an out of memory error.
|
||||||
|
// Calling this function polls various fences in order to determine what the GPU has
|
||||||
|
// already processed, and frees the resources that are no longer needed.
|
||||||
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
|
// Whenever the window resizes we need to recreate everything dependent on the window size.
|
||||||
|
// In this example that includes the swapchain, the framebuffers and the dynamic state viewport.
|
||||||
|
if recreate_swapchain {
|
||||||
|
// Use the new dimensions of the window.
|
||||||
|
|
||||||
|
let (new_swapchain, new_images) =
|
||||||
|
match swapchain.recreate(SwapchainCreateInfo {
|
||||||
|
image_extent: dimensions.into(),
|
||||||
|
..swapchain.create_info()
|
||||||
|
}) {
|
||||||
|
Ok(r) => r,
|
||||||
|
// This error tends to happen when the user is manually resizing the window.
|
||||||
|
// Simply restarting the loop is the easiest way to fix this issue.
|
||||||
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
|
Err(e) => panic!("Failed to recreate swapchain: {e:?}"),
|
||||||
|
};
|
||||||
|
|
||||||
|
swapchain = new_swapchain;
|
||||||
|
// Because framebuffers contains an Arc on the old swapchain, we need to
|
||||||
|
// recreate framebuffers as well.
|
||||||
|
framebuffers = window_size_dependent_setup(
|
||||||
|
&memory_allocator,
|
||||||
|
&new_images,
|
||||||
|
render_pass.clone(),
|
||||||
|
&mut viewport,
|
||||||
|
);
|
||||||
|
recreate_swapchain = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uniform_data = {
|
||||||
|
let elapsed = rotation_start.elapsed();
|
||||||
|
let rotation =
|
||||||
|
elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000.0;
|
||||||
|
let rotation = Matrix3::from_angle_y(Rad(rotation as f32));
|
||||||
|
|
||||||
|
// note: this teapot was meant for OpenGL where the origin is at the lower left
|
||||||
|
// instead the origin is at the upper left in Vulkan, so we reverse the Y axis
|
||||||
|
let aspect_ratio =
|
||||||
|
swapchain.image_extent()[0] as f32 / swapchain.image_extent()[1] as f32;
|
||||||
|
let proj = cgmath::perspective(
|
||||||
|
Rad(std::f32::consts::FRAC_PI_2),
|
||||||
|
aspect_ratio,
|
||||||
|
0.01,
|
||||||
|
100.0,
|
||||||
|
);
|
||||||
|
let view = Matrix4::look_at_rh(
|
||||||
|
Point3::new(0.3, 0.3, 1.0),
|
||||||
|
Point3::new(0.0, 0.0, 0.0),
|
||||||
|
Vector3::new(0.0, -1.0, 0.0),
|
||||||
|
);
|
||||||
|
let scale = Matrix4::from_scale(0.01);
|
||||||
|
|
||||||
|
vs::ty::PushConstantData {
|
||||||
|
world: Matrix4::from(rotation).into(),
|
||||||
|
view: (view * scale).into(),
|
||||||
|
proj: proj.into(),
|
||||||
|
}
|
||||||
|
|
||||||
|
/*println!(
|
||||||
|
"world: {:?} view: {:?} proj: {:?}",
|
||||||
|
uniform_data.world, uniform_data.view, uniform_data.proj
|
||||||
|
);*/
|
||||||
|
|
||||||
|
//uniform_buffer.from_data(uniform_data).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
//let layout = pipeline.layout().set_layouts().get(0).unwrap();
|
||||||
|
/*let set = PersistentDescriptorSet::new(
|
||||||
|
&memory_allocator,
|
||||||
|
layout.clone(),
|
||||||
|
[WriteDescriptorSet::buffer(0, uniform_buffer_subbuffer)],
|
||||||
|
)
|
||||||
|
.unwrap();*/
|
||||||
|
|
||||||
|
// Before we can draw on the output, we have to *acquire* an image from the swapchain. If
|
||||||
|
// no image is available (which happens if you submit draw commands too quickly), then the
|
||||||
|
// function will block.
|
||||||
|
// This operation returns the index of the image that we are allowed to draw upon.
|
||||||
|
//
|
||||||
|
// This function can block if no image is available. The parameter is an optional timeout
|
||||||
|
// after which the function call will return an error.
|
||||||
|
let (image_index, suboptimal, acquire_future) =
|
||||||
|
match acquire_next_image(swapchain.clone(), None) {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(AcquireError::OutOfDate) => {
|
||||||
|
recreate_swapchain = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Err(e) => panic!("Failed to acquire next image: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
|
// acquire_next_image can be successful, but suboptimal. This means that the swapchain image
|
||||||
|
// will still work, but it may not display correctly. With some drivers this can be when
|
||||||
|
// the window resizes, but it may not cause the swapchain to become out of date.
|
||||||
|
if suboptimal {
|
||||||
|
recreate_swapchain = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In order to draw, we have to build a *command buffer*. The command buffer object holds
|
||||||
|
// the list of commands that are going to be executed.
|
||||||
|
//
|
||||||
|
// Building a command buffer is an expensive operation (usually a few hundred
|
||||||
|
// microseconds), but it is known to be a hot path in the driver and is expected to be
|
||||||
|
// optimized.
|
||||||
|
//
|
||||||
|
// Note that we have to pass a queue family when we create the command buffer. The command
|
||||||
|
// buffer will only be executable on that given queue family.
|
||||||
|
let mut builder = AutoCommandBufferBuilder::primary(
|
||||||
|
&command_buffer_allocator,
|
||||||
|
queue.queue_family_index(),
|
||||||
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
builder
|
||||||
|
// Before we can draw, we have to *enter a render pass*.
|
||||||
|
.begin_render_pass(
|
||||||
|
RenderPassBeginInfo {
|
||||||
|
// A list of values to clear the attachments with. This list contains
|
||||||
|
// one item for each attachment in the render pass. In this case,
|
||||||
|
// there is only one attachment, and we clear it with a blue color.
|
||||||
|
//
|
||||||
|
// Only attachments that have `LoadOp::Clear` are provided with clear
|
||||||
|
// values, any others should use `ClearValue::None` as the clear value.
|
||||||
|
clear_values: vec![
|
||||||
|
Some([0.12, 0.1, 0.1, 1.0].into()),
|
||||||
|
Some(1.0.into()),
|
||||||
|
],
|
||||||
|
..RenderPassBeginInfo::framebuffer(
|
||||||
|
framebuffers[image_index as usize].clone(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
// The contents of the first (and only) subpass. This can be either
|
||||||
|
// `Inline` or `SecondaryCommandBuffers`. The latter is a bit more advanced
|
||||||
|
// and is not covered here.
|
||||||
|
SubpassContents::Inline,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
// We are now inside the first subpass of the render pass. We add a draw command.
|
||||||
|
//
|
||||||
|
// The last two parameters contain the list of resources to pass to the shaders.
|
||||||
|
// Since we used an `EmptyPipeline` object, the objects have to be `()`.
|
||||||
|
.set_viewport(0, [viewport.clone()])
|
||||||
|
.bind_pipeline_graphics(pipeline.clone())
|
||||||
|
/*.bind_descriptor_sets(
|
||||||
|
PipelineBindPoint::Graphics,
|
||||||
|
pipeline.layout().clone(),
|
||||||
|
0,
|
||||||
|
set,
|
||||||
|
)*/
|
||||||
|
.bind_vertex_buffers(0, vertex_buffer.clone())
|
||||||
|
.push_constants(pipeline.layout().clone(), 0, uniform_data)
|
||||||
|
.draw(vertex_buffer.len() as u32, 1, 0, 0)
|
||||||
|
.unwrap()
|
||||||
|
// We leave the render pass. Note that if we had multiple
|
||||||
|
// subpasses we could have called `next_subpass` to jump to the next subpass.
|
||||||
|
.end_render_pass()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Finish building the command buffer by calling `build`.
|
||||||
|
let command_buffer = builder.build().unwrap();
|
||||||
|
|
||||||
|
let future = previous_frame_end
|
||||||
|
.take()
|
||||||
|
.unwrap()
|
||||||
|
.join(acquire_future)
|
||||||
|
.then_execute(queue.clone(), command_buffer)
|
||||||
|
.unwrap()
|
||||||
|
// The color output is now expected to contain our triangle. But in order to show it on
|
||||||
|
// the screen, we have to *present* the image by calling `present`.
|
||||||
|
//
|
||||||
|
// This function does not actually present the image immediately. Instead it submits a
|
||||||
|
// present command at the end of the queue. This means that it will only be presented once
|
||||||
|
// the GPU has finished executing the command buffer that draws the triangle.
|
||||||
|
.then_swapchain_present(
|
||||||
|
queue.clone(),
|
||||||
|
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
|
||||||
|
)
|
||||||
|
.then_signal_fence_and_flush();
|
||||||
|
|
||||||
|
match future {
|
||||||
|
Ok(future) => {
|
||||||
|
previous_frame_end = Some(future.boxed());
|
||||||
|
}
|
||||||
|
Err(FlushError::OutOfDate) => {
|
||||||
|
recreate_swapchain = true;
|
||||||
|
previous_frame_end = Some(sync::now(device.clone()).boxed());
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("Failed to flush future: {:?}", e);
|
||||||
|
previous_frame_end = Some(sync::now(device.clone()).boxed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This method is called once during initialization, then again whenever the window is resized
|
||||||
|
fn window_size_dependent_setup(
|
||||||
|
allocator: &StandardMemoryAllocator,
|
||||||
|
images: &[Arc<SwapchainImage>],
|
||||||
|
render_pass: Arc<RenderPass>,
|
||||||
|
viewport: &mut Viewport,
|
||||||
|
) -> Vec<Arc<Framebuffer>> {
|
||||||
|
let dimensions = images[0].dimensions().width_height();
|
||||||
|
viewport.dimensions = [dimensions[0] as f32, dimensions[1] as f32];
|
||||||
|
|
||||||
|
let depth_buffer = ImageView::new_default(
|
||||||
|
AttachmentImage::transient(allocator, dimensions, Format::D16_UNORM).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
images
|
||||||
|
.iter()
|
||||||
|
.map(|image| {
|
||||||
|
let view = ImageView::new_default(image.clone()).unwrap();
|
||||||
|
Framebuffer::new(
|
||||||
|
render_pass.clone(),
|
||||||
|
FramebufferCreateInfo {
|
||||||
|
attachments: vec![view, depth_buffer.clone()],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user